# Source: handler.js

    /** @file
    This contains the high-level commands for transitioning between the different annotation tool states.  They are: REST, DRAW, SELECTED, QUERY.
    */

    // Handles all of the user's actions and delegates tasks to other classes.
    // Also keeps track of global information.
    var REST_CANVAS = 1;
    var DRAW_CANVAS = 2;
    var SELECTED_CANVAS = 3;
    var QUERY_CANVAS = 4;

    // Global variable indicating which canvas is active:
    var active_canvas = REST_CANVAS;

    function handler() {

        // *******************************************
        // Public methods:
        // *******************************************

        // Handles when the user presses the delete button in response to
        // the "What is this object?" popup bubble.
        this.WhatIsThisObjectDeleteButton = function () {
          submission_edited = 0;
          this.QueryToRest();
        };

        // Submits the object label in response to the edit/delete popup bubble.
        this.SubmitEditLabel = function () {
          submission_edited = 1;
          var anno = select_anno;

          // object name
          old_name = LMgetObjectField(LM_xml,anno.anno_id,'name');
          if(document.getElementById('objEnter')) new_name = RemoveSpecialChars(document.getElementById('objEnter').value);
          else new_name = RemoveSpecialChars(adjust_objEnter);

          var re = /[a-zA-Z0-9]/;
          if(!re.test(new_name)) {
    	alert('Please enter an object name');
    	return;
          }

          if (use_attributes) {
    	// occlusion field
    	if (document.getElementById('occluded')) new_occluded = RemoveSpecialChars(document.getElementById('occluded').value);
    	else new_occluded = RemoveSpecialChars(adjust_occluded);

    	// attributes field
    	if(document.getElementById('attributes')) new_attributes = RemoveSpecialChars(document.getElementById('attributes').value);
    	else new_attributes = RemoveSpecialChars(adjust_attributes);
          }

          StopEditEvent();

          // Insert data to write to logfile:
          if(editedControlPoints) InsertServerLogData('cpts_modified');
          else InsertServerLogData('cpts_not_modified');

          // Object index:
          var obj_ndx = anno.anno_id;

          // Pointer to object:
          var curr_obj = $(LM_xml).children("annotation").children("object").eq(obj_ndx);

          // Set fields:
          curr_obj.children("name").text(new_name);
          if(curr_obj.children("automatic").length > 0) curr_obj.children("automatic").text("0");

          // Insert attributes (and create field if it is not there):
          if(curr_obj.children("attributes").length>0) curr_obj.children("attributes").text(new_attributes);
          else curr_obj.append("<attributes>" + new_attributes + "</attributes>");

          if(curr_obj.children("occluded").length>0) curr_obj.children("occluded").text(new_occluded);
          else curr_obj.append("<occluded>" + new_occluded + "</occluded>");

          if(editedControlPoints) {
    	for(var jj=0; jj < AllAnnotations[obj_ndx].GetPtsX().length; jj++) {
    	  curr_obj.children("polygon").children("pt").eq(jj).children("x").text(AllAnnotations[obj_ndx].GetPtsX()[jj]);
    	  curr_obj.children("polygon").children("pt").eq(jj).children("y").text(AllAnnotations[obj_ndx].GetPtsY()[jj]);
    	}
          }

          // Write XML to server:
          WriteXML(SubmitXmlUrl,LM_xml,function(){return;});

          // Refresh object list:
          if(view_ObjList) {
    	RenderObjectList();
    	ChangeLinkColorFG(anno.GetAnnoID());
          }
        };

        // Handles when the user presses the delete button in response to
        // the edit popup bubble.
        this.EditBubbleDeleteButton = function () {
            var idx = select_anno.GetAnnoID();

            if((IsUserAnonymous() || (!IsCreator(select_anno.GetUsername()))) && (!IsUserAdmin()) && (idx<num_orig_anno) && !action_DeleteExistingObjects) {
                alert('You do not have permission to delete this polygon');
                return;
            }

            if(idx>=num_orig_anno) {
                global_count--;
            }

            submission_edited = 0;

            // Insert data for server logfile:
            old_name = LMgetObjectField(LM_xml,select_anno.anno_id,'name');
            new_name = old_name;
            WriteLogMsg('*Deleting_object');
            InsertServerLogData('cpts_not_modified');

            // Set <deleted> in LM_xml:
            $(LM_xml).children("annotation").children("object").eq(idx).children("deleted").text('1');

            // Remove all the part dependencies for the deleted object
            removeAllParts(idx);

            // Write XML to server:
            WriteXML(SubmitXmlUrl,LM_xml,function(){return;});

    	// Refresh object list:
            if(view_ObjList) RenderObjectList();

            unselectObjects(); // Perhaps this should go elsewhere...
            StopEditEvent();
        };

        // Handles when the user clicks on the link for an annotation.
        this.AnnotationLinkClick = function (idx) {
          if(active_canvas==REST_CANVAS) StartEditEvent(idx,null);
          else if(active_canvas==SELECTED_CANVAS) {
    	var anno_id = select_anno.GetAnnoID();
    	if(edit_popup_open && (idx==anno_id)) StopEditEvent();
          }
        };

        // Handles when the user moves the mouse over an annotation link.
        this.AnnotationLinkMouseOver = function (a) {
            if(active_canvas!=SELECTED_CANVAS) selectObject(a);
        };

        // Handles when the user moves the mouse away from an annotation link.
        this.AnnotationLinkMouseOut = function () {
            if(active_canvas!=SELECTED_CANVAS) unselectObjects();
        };

        // Handles when the user moves the mouse over a polygon on the drawing
        // canvas.
        this.CanvasMouseMove = function (event,pp) {
            var x = GetEventPosX(event);
            var y = GetEventPosY(event);
            if(IsNearPolygon(x,y,pp)) selectObject(pp);
            else unselectObjects();
        };

        // Submits the object label in response to the "What is this object?"
        // popup bubble. THIS FUNCTION IS A MESS!!!!
        this.SubmitQuery = function () {
          var nn;
          var anno;

          // If the attributes are active, read the fields.
          if (use_attributes) {
    	// get attributes (is the field exists)
    	if(document.getElementById('attributes')) new_attributes = RemoveSpecialChars(document.getElementById('attributes').value);
    	else new_attributes = "";

    	// get occlusion field (is the field exists)
    	if (document.getElementById('occluded')) new_occluded = RemoveSpecialChars(document.getElementById('occluded').value);
    	else new_occluded = "";
          }

          if((object_choices!='...') && (object_choices.length==1)) {
    	nn = RemoveSpecialChars(object_choices[0]);
    	active_canvas = REST_CANVAS;

    	// Move draw canvas to the back:
    	document.getElementById('draw_canvas').style.zIndex = -2;
    	document.getElementById('draw_canvas_div').style.zIndex = -2;

    	// Remove polygon from the draw canvas:
    	var anno = null;
    	if(draw_anno) {
    	  draw_anno.DeletePolygon();
    	  anno = draw_anno;
    	  draw_anno = null;
    	}
          }
          else {
    	nn = RemoveSpecialChars(document.getElementById('objEnter').value);
    	anno = this.QueryToRest();
          }

          var re = /[a-zA-Z0-9]/;
          if(!re.test(nn)) {
    	alert('Please enter an object name');
    	return;
          }

          // Update old and new object names for logfile:
          new_name = nn;
          old_name = nn;

          submission_edited = 0;
          global_count++;

          // Insert data for server logfile:
          InsertServerLogData('cpts_not_modified');

          // Insert data into XML:
          var html_str = '<object>';
          html_str += '<name>' + new_name + '</name>';
          html_str += '<deleted>0</deleted>';
          html_str += '<verified>0</verified>';
          if(use_attributes) {
    	html_str += '<occluded>' + new_occluded + '</occluded>';
    	html_str += '<attributes>' + new_attributes + '</attributes>';
          }
          html_str += '<parts><hasparts></hasparts><ispartof></ispartof></parts>';
          var ts = GetTimeStamp();
          if(ts.length==20) html_str += '<date>' + ts + '</date>';
          html_str += '<id>' + anno.anno_id + '</id>';

          if(anno.GetType() == 1) {
    	/*************************************************************/
    	/*************************************************************/
    	// Scribble: Add annotation to LM_xml:
    	html_str += '<segm>';
    	html_str += '<username>' + username + '</username>';

    	html_str += '<box>';
    	html_str += '<xmin>' + anno.GetPtsX()[0] + '</xmin>';
    	html_str += '<ymin>' + anno.GetPtsY()[0] + '</ymin>';
    	html_str += '<xmax>' + anno.GetPtsX()[1] + '</xmax>';
    	html_str += '<ymax>' + anno.GetPtsY()[2] + '</ymax>';
    	html_str += '</box>';

    	html_str += '<mask>'+ anno.GetImName()+'</mask>';

    	html_str += '<scribbles>';
    	html_str += '<xmin>' + anno.GetCornerLX() + '</xmin>';
    	html_str += '<ymin>' + anno.GetCornerLY() + '</ymin>';
    	html_str += '<xmax>' + anno.GetCornerRX() + '</xmax>';
    	html_str += '<ymax>' + anno.GetCornerRY() + '</ymax>';
    	html_str += '<scribble_name>'+ anno.GetScribbleName()+'</scribble_name>';
    	html_str += '</scribbles>';

    	html_str += '</segm>';
    	html_str += '</object>';
    	$(LM_xml).children("annotation").append($(html_str));
    	/*************************************************************/
    	/*************************************************************/
          }
          else {
    	html_str += '<polygon>';
    	html_str += '<username>' + username + '</username>';
    	for(var jj=0; jj < anno.GetPtsX().length; jj++) {
    	  html_str += '<pt>';
    	  html_str += '<x>' + anno.GetPtsX()[jj] + '</x>';
    	  html_str += '<y>' + anno.GetPtsY()[jj] + '</y>';
    	  html_str += '</pt>';
    	}
    	html_str += '</polygon>';
    	html_str += '</object>';
    	$(LM_xml).children("annotation").append($(html_str));
          }

          AllAnnotations.push(anno);

          if(!anno.GetDeleted()||view_Deleted) {
    	main_canvas.AttachAnnotation(anno);
    	anno.RenderAnnotation('rest');
          }

          /*************************************************************/
          /*************************************************************/
          // Scribble: Clean scribbles.
          if(anno.GetType() == 1) {
    	scribble_canvas.cleanscribbles();
    	scribble_canvas.scribble_image = "";
    	scribble_canvas.colorseg = Math.floor(Math.random()*14);
          }
          /*************************************************************/
          /*************************************************************/

          // Write XML to server:
          WriteXML(SubmitXmlUrl,LM_xml,function(){return;});

          if(view_ObjList) RenderObjectList();

          var m = main_media.GetFileInfo().GetMode();
          if(m=='mt') {
    	document.getElementById('object_name').value=new_name;
    	document.getElementById('number_objects').value=global_count;
    	document.getElementById('LMurl').value = LMbaseurl + '?collection=LabelMe&mode=i&folder=' + main_media.GetFileInfo().GetDirName() + '&image=' + main_media.GetFileInfo().GetImName();
    	if(global_count >= mt_N) document.getElementById('mt_submit').disabled=false;
          }
        };

        // Handles when we wish to change from "query" to "rest".
        this.QueryToRest = function () {
            active_canvas = REST_CANVAS;

    	// Move query canvas to the back:
    	document.getElementById('query_canvas').style.zIndex = -2;
    	document.getElementById('query_canvas_div').style.zIndex = -2;

    	// Remove polygon from the query canvas:
    	if(query_anno) query_anno.DeletePolygon();
    	var anno = query_anno;
    	query_anno = null;

    	CloseQueryPopup();
    	main_media.ScrollbarsOn();

            return anno;
        };

        // Handles when the user presses a key while interacting with the tool.
        this.KeyPress = function (event) {
            // Delete event: 46 - delete key; 8 - backspace key
            if(((event.keyCode==46) || (event.keyCode==8)) && !wait_for_input && !edit_popup_open && !username_flag) {
                // Determine whether we are deleting a complete or partially
                // complete polygon.
                if(!main_handler.EraseSegment()) DeleteSelectedPolygon();
            }
            // 27 - Esc key
            // Close edit popup if it is open.
            if(event.keyCode==27 && edit_popup_open) StopEditEvent();
        };

        // Handles when the user erases a segment.
        this.EraseSegment = function () {
            if(draw_anno && !draw_anno.DeleteLastControlPoint()) {
                submission_edited = 0;
                StopDrawEvent();
            }
            return draw_anno;
        };

        // *******************************************
        // Private methods:
        // *******************************************

    }