"""mems.instrument.client.tk.state.

Class that acts as the command handler for the ScopeConnection,
and stores the microscope's state.
"""

__revision__ = "$Id: state.py,v 1.30 2002/02/19 23:17:15 akuchlin Exp $"

import string, cStringIO
from PIL import Image
import time

# Import JpegImagePlugin explicitly to catch it when freezing the client
from PIL import JpegImagePlugin

from mems.instrument import protocols

__timing__ = 0                          # Set to 1 to display timing data

class MicroscopeState:
    def __init__ (self, client):
        self.client = client
        
        # Scope parameters
        self.x = self.y = self.z = self.angle = self.light = 0
        self.magnification = 5
        self.mode = 'Brightfield'
        self.aperture = 1
        self.x_scale = self.y_scale = 1.0

        # Boolean denoting whether autofocus is on
        self.autofocus = 1
	self.z_unit = 1        # Increments in which z can be adjusted
        
        # Boolean denoting whether someone is in control of the microscope
        self.taken = 0

        # Boolean denoting whether this user is in control of the microscope
        self.in_control = 0

        # List of connected users
        self.userlist = []
        self.controller_id = None

        # Connection object
        self.cmd_connection = None

        # Annotation display
        self.draw_annotation = protocols.ANNOTATE_NONE
        self.x1 = self.y1 = None
        self.x2 = self.y2 = None
        
    def get_cmd_connection (self):
        return self.cmd_connection

    def set_cmd_connection (self, conn):
        if self.cmd_connection is not None:
            self.cmd_connection.close()
        self.cmd_connection = conn
        if conn is not None:
            conn.add_handler(self)
        
    def send_message (self, msg):
        if self.cmd_connection is not None:
            self.cmd_connection.send_message(msg)

    def move (self, x = None, y = None, z = None,
	     angle = None, magnification = None,
             mode = None, aperture = None, light = None):
        "Move the scope to a new position and setting"

	if not self.in_control:
            # XXX should log an error here, because this method
            # really shouldn't be called unless the user is in control.
            return
        
        args = []
        if x is not None: args.append('x=%i' % x)
        if y is not None: args.append('y=%i' % y) 
        if z is not None: args.append('z=%i' % z)
        if angle is not None:
            args.append('angle=%i' % angle)
        if magnification is not None:
            args.append('magnification=%i' % magnification)
        if mode is not None:
            args.append('mode=%s' % mode)
        if aperture is not None:
            args.append('aperture=%i' % aperture)
        if light is not None:
            args.append('light=%i' % light)
        args = string.join(args, ' ')
        self.send_message('move ' + args)

    # Messages updating the microscope's status
    def cmd_scope (self, sock, x=None, y=None, z=None,
                 magnification=None, mode=None,
                 light=None, aperture=None, autofocus=None,
                 x_scale=None, y_scale=None, angle=None):
        self.x, self.y = x, y
        self.z = z
        self.angle = angle
        self.magnification = magnification

        mode = mode.capitalize()
        if mode == 'Icr': mode = 'ICR'
        self.mode = mode
        
        self.aperture = aperture
        self.light = light

        self.x_scale = float(x_scale)
        self.y_scale = float(y_scale)

        self.client.state_changed()

    def cmd_autofocus (self, sock, args):
        if len(args) and string.lower(args[0]) == 'on':
            self.autofocus = 1
        else:
            self.autofocus = 0
            
        self.client.state_changed()

    # Messages dealing with image annotations
    def cmd_rectangle (self, sock, x1, y1, x2, y2):
        if self.in_control:
            return
        self.draw_annotation = protocols.ANNOTATE_RECTANGLE
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2
        self.client.image_changed()
        
    def cmd_measure (self, sock, x1, y1, x2, y2):
        if self.in_control:
            return
        self.draw_annotation = protocols.ANNOTATE_MEASUREMENT
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2
        self.client.image_changed()

    # Messages dealing with chatting
    def cmd_chatmsg (self, sock, id, msg):
        self.client.chat_arrived(id, msg)

    def cmd_userlistdelete (self, sock, id):
        if id in self.userlist:
            self.userlist.remove(id)
            self.client.userlist_changed(self.userlist, self.controller_id)

    def cmd_userlistadd (self, sock, id):
        self.userlist.append(id)
        self.userlist.sort()
        self.client.userlist_changed(self.userlist, self.controller_id)
            

    # Messages dealing with microscope control
    def cmd_take (self, sock):
        self.taken = 1
        self.in_control = 1
        self.controller_id = self.client.userid
        self.client.control_changed()
        self.client.userlist_changed(self.userlist, self.controller_id)

    def cmd_cede (self, sock):
        self.in_control = 0
        self.taken = 0
        self.controller_id = None
        self.client.control_changed()
        self.client.userlist_changed(self.userlist, self.controller_id)
        
    def cmd_taken (self, sock, id):
        self.in_control = 0
        self.taken = 1
        self.controller_id = id
        self.client.control_changed()
        self.client.userlist_changed(self.userlist, self.controller_id)

