﻿// MarkerController [start]

var MarkerConsts = {
  IDLE: 0,
  START_MARKER: 1,
  DRAG_MARKER: 2,
  RESIZE_MARKER: 3,
  DELETE_MARKER: 4,
  HOVER: 5,
  HOVER_INPUT: 6,
  HOVER_NOTATION: 7,
  AUTOCOMPLETE: 8,
  MESSAGE_OPEN: 9,
  INIT: 10,
  MIN_SIZE: 30,
  NOTATION_WIDTH: 150,
  NOTATION_HEIGHT: 18,
  NOTATION_PADDING: 3,
  PERSON_MESSAGE: 0,
  NOTE_MESSAGE: 1,
  DEFAULT_WIDTH: 80,
  DEFAULT_HEIGHT: 90,
  PERSON_MARKER: 0,
  IMAGE_NOTE: 1
}

function reverseLookupMode(curMode){
  for (var prop in MarkerConsts)
    if (MarkerConsts[prop] == curMode)
      return prop;
  return "Unknown";
}

function MarkerController(){
  this.init();
}

MarkerController.prototype.init = function() {
  if (typeof (this.canvas) != "undefined") {
    this.canvas.onmousedown = null;
    AssetPageRemoveChildren(this.canvas);
    this.canvas.style.display = "none";
    this.canvas = undefined;
  }
  this.mode = MarkerConsts.INIT;
  this.drawObject = 0;
  this.markers = new Object();
  this.markerCount = 0;
  this.messageIsOpen = false;
  this.tempMarker = null;
  if (this.mouseOverInterval) {
    clearInterval(this.mouseOverInterval);
    this.mouseOverInterval = null;
  }
}

MarkerController.prototype.setCanvas = function(assetID) {
  if (assetPage.assetData.CanAddMarker == false) return false;
  var contactID, i, email;
  if (typeof (this.canvas) == "undefined") {
    if ($get("Marker_canvas") == null) return false;
    this.canvas = $get("Marker_canvas");
  }
  this.canvasPos = MarkerGetPos(this.canvas);
  this.assetID = assetID;
  this.canvas.onmousedown = function() { markerController.mouseDown() };
  this.canvasWidth = this.canvas.offsetWidth;
  this.canvasHeight = this.canvas.offsetHeight;
  this.canvasVisible = true;
  this.autoCompleteData = new Array();
  var curContact, viewerContact;
  var curContactList = new Array();
  for (contactID in ContactCloud) {
    if (ContactCloud[contactID].TargetTypeID == TargetTypes.CONTACT) {
      curContactList.push(new Array(ContactCloud[contactID].Name, contactID));
    }
    if (ContactCloud[contactID].TargetTypeID == TargetTypes.VIEWER) {
      email = (ContactCloud[contactID].Email == undefined) ? "" : ContactCloud[contactID].Email;
      viewerContact = {
        name: ContactCloud[contactID].Name,
        avatar: ContactCloud[contactID].SmallAvatarURL,
        email: email,
        id: contactID,
        isViewer: true
      };
    }
  }
  curContactList.sort();
  this.autoCompleteData.push(viewerContact);
  for (i = 0; i < curContactList.length; i++) {
    this.autoCompleteData.push({
      name: curContactList[i][0],
      avatar: ContactCloud[curContactList[i][1]].SmallAvatarURL,
      email: ContactCloud[curContactList[i][1]].Email,
      id: curContactList[i][1],
      isViewer: false
    });
  }
  AutoComplete_Create(this.autoCompleteData, 6);
  this.setCueuedMarkers();
  this.mode = MarkerConsts.IDLE;
  setTimeout(ContextDelegate(this, this.restoreMouseOverInterval), 1000);
  return true;
}

MarkerController.prototype.mouseMove = function() {
  if (this.canvasPos == undefined) return;
  var mouseLocal = this.mouseToLocal();
  switch (this.mode) {
    case MarkerConsts.START_MARKER:
      this.tempMarker.startResize();
      break;
    case MarkerConsts.DRAG_MARKER:
      this.tempMarker.dragTo(mouseLocal.left - this.dragOffset.left, mouseLocal.top - this.dragOffset.top);
      break;
    case MarkerConsts.RESIZE_MARKER:
      this.tempMarker.handleResize(mouseLocal.left - this.dragOffset.left, mouseLocal.top - this.dragOffset.top);
      break;
  }
}

MarkerController.prototype.mouseDown = function() {
  if (AutoComplete_isVisible()) return true;
  if (this.messageIsOpen) return true;
  if (!this.canvasVisible) return true;
  if (this.mode == MarkerConsts.IDLE) {
    if (this.tempMarker != null) {
      if (this.tempMarker.elements.notation.text == "") {
        this.removeElement(this.tempMarker.id);
        this.tempMarker = null;
      }
    }
    this.selectNone();
    this.mode = MarkerConsts.START_MARKER;
    this.tempMarker = new Marker(this, this.markerCount++);
    this.markers[this.tempMarker.id] = this.tempMarker;
    this.tempMarker.start();
    this.redraw();
  }
}

MarkerController.prototype.mouseUp = function() {
  if (AutoComplete_isVisible()) return;
  if (this.messageIsOpen) return;
  switch (this.mode) {
    case MarkerConsts.START_MARKER:
      this.tempMarker.stopResize();
      break;
    case MarkerConsts.DRAG_MARKER:
      this.mode = MarkerConsts.IDLE;
      if (tempX != this.mouseX || tempY != this.mouseY) {
        this.updateServer();
      }
      this.tempMarker.stopDrag();
      this.focusOnInput();
      break;
    case MarkerConsts.RESIZE_MARKER:
      if (tempX != this.mouseX || tempY != mouseY) {
        this.updateServer();
      }
      this.focusOnInput();
      break; /*
    case MarkerConsts.DELETE_MARKER:
      if (this.tempMarker.elements.notation.text == "")
        this.removeMarker();
      else
        this.cancelMarker();
      break;*/
    case MarkerConsts.HOVER_INPUT:
      AutoComplete_Attach(this.tempMarker.elements.input);
      $get(this.tempMarker.elements.input.id + "_inp").focus();
      return;
    case MarkerConsts.AUTOCOMPLETE:
      return;
  }
  this.mode = MarkerConsts.IDLE;
  //enableDragSelect(true);
}

MarkerController.prototype.focusOnInput = function() {
  AutoComplete_Attach(this.tempMarker.elements.input);
  this.tempMarker.placeInput();
  this.tempMarker.elements.notation.setStyleValue("visibility", "hidden");
  this.tempMarker.elements.input.setStyleValue("visibility", "visible");
  $get(this.tempMarker.elements.input.id + "_inp").focus();
}

MarkerController.prototype.updateServer = function() {
  if (this.tempMarker.data.ID != undefined) {
    var percentagePos = this.tempMarker.rectToPercentage();
    var params = new Array(
    { name: "MarkerID", value: this.tempMarker.data.ID },
    { name: "Left", value: percentagePos.left },
    { name: "Top", value: percentagePos.top },
    { name: "Width", value: percentagePos.width },
    { name: "Height", value: percentagePos.height },
    { name: "SerType", value: 2 });
    assetPage.markerUpdated('update', this.tempMarker.data);
    assetPage.message.setTemplateMessage("processing");
    if (this.tempMarker.data.MarkedUserID == 0)
      params.push({ name: "Note", value: this.tempMarker.data.Note });
    else {
      params.push({ name: "MarkedUserID", value: this.tempMarker.data.MarkedUserID });
    }
    executeWebRequest("Assets.UpdateMarker", params, { onSuccessFunction: updateMarkerSuccess, onFailureFunction: markersResultFail });
  }
}

MarkerController.prototype.redraw = function() {
  for (var prop in this.markers) {
    if (!this.markers[prop].onCanvas) {
      this.canvas.appendChild(this.markers[prop].getHtml());
      this.markers[prop].setHtmlObjects();
      this.markers[prop].onCanvas = true;
    }
  }
}

MarkerController.prototype.removeElement = function(curID) {
  if (this.markers[curID] == undefined) return;
  this.canvas.removeChild(this.markers[curID].elements.container.htmlObject);
  delete (this.markers[curID]);
}

MarkerController.prototype.selectNone = function() {
  this.focus = -1;
  this.tempMarker = null;
  for (var prop in this.markers) {
    this.markers[prop].focus(false);
  }
}

MarkerController.prototype.hoverIn = function(markerID, elementType) {
  switch (this.mode) {
    case MarkerConsts.START_MARKER:
    case MarkerConsts.DRAG_MARKER:
    case MarkerConsts.RESIZE_MARKER:
      return;
  }
  this.mode = MarkerConsts.HOVER;
  this.markers[markerID].hoverIn(elementType);
}

MarkerController.prototype.hoverOut = function(markerID, elementType) {
  switch (this.mode){
    case MarkerConsts.START_MARKER:
    case MarkerConsts.DRAG_MARKER:
    case MarkerConsts.RESIZE_MARKER:
      return;
  }
  this.mode = MarkerConsts.IDLE;
  this.markers[markerID].hoverOut(elementType);
}

MarkerController.prototype.removeMarker = function(elementID) {
  if (elementID != undefined) {
    this.tempMarker = this.markers[elementID];
  }
  if (this.tempMarker.data.ID != undefined) {
    assetPage.message.setTemplateMessage("processing");
    var params = new Array(
      { name: "MarkerID", value: this.tempMarker.data.ID },
      { name: "SerType", value: 2 });
    executeWebRequest("Assets.DeleteMarker", params, { onSuccessFunction: deleteMarkerSuccess, onFailureFunction: markersResultFail });
    assetPage.markerUpdated('delete', this.tempMarker.data);
  }
  this.removeElement(this.tempMarker.id);
  this.tempMarker = null;
  this.selectNone();
  AutoComplete_HideDropdown();
  this.mode = MarkerConsts.IDLE;
}

MarkerController.prototype.startDrag = function(markerID, elementType) {
  if (this.mode == MarkerConsts.HOVER_INPUT)
    return;
  if (this.messageIsOpen) return;
  var canDelete = (this.markers[markerID].data.CanDelete == undefined || this.markers[markerID].data.CanDelete == true);
  var canUpdate = (this.markers[markerID].data.CanUpdate == undefined || this.markers[markerID].data.CanUpdate == true);
  this.selectNone();
  this.tempMarker = this.markers[markerID];
  if (canDelete && !canUpdate && elementType == "close") {
    this.mode = MarkerConsts.DELETE_MARKER;
    return;
  } else if (!canUpdate)
    return;
  this.focus = markerID;
  this.tempMarker.focus(true);
  this.mouseX = tempX;
  this.mouseY = tempY;
  var mouseLocal = this.mouseToLocal();
  switch (elementType) {
    case "handle":
      var handleLeft = this.tempMarker.left + parseInt(this.tempMarker.elements.handle.htmlObject.style.left);
      var handleTop = this.tempMarker.top + parseInt(this.tempMarker.elements.handle.htmlObject.style.top);
      this.dragOffset = { left: mouseLocal.left - handleLeft, top: mouseLocal.top - handleTop };
      this.mode = MarkerConsts.RESIZE_MARKER;
      break;
    case "close":
      this.mode = MarkerConsts.DELETE_MARKER;
      break;
    case "input":
      this.mode = MarkerConsts.HOVER_INPUT;
      break;
    case "notation":
      this.tempMarker.placeInput();
      this.tempMarker.elements.input.inputObject.value = this.tempMarker.elements.notation.text;
      this.tempMarker.elements.notation.setStyleValue("visibility", "hidden");
      this.tempMarker.elements.input.setStyleValue("visibility", "visible");
      this.mode = MarkerConsts.HOVER_INPUT;
      AutoComplete_Attach(this.tempMarker.elements.input);
      $get(this.tempMarker.elements.input.id + "_inp").focus();
      break;
    default:
      this.dragOffset = { left: mouseLocal.left - parseInt(this.tempMarker.elements.container.htmlObject.style.left), top: mouseLocal.top - parseInt(this.tempMarker.elements.container.htmlObject.style.top) };
      this.mode = MarkerConsts.DRAG_MARKER;
      this.tempMarker.startDrag();
      break;
  }
}

MarkerController.prototype.pageResize = function() {
  //this.canvasPos = MarkerGetPos(this.canvas);
}

MarkerController.prototype.checkMouseOver = function() {
  //$get("AssetPage_num_views").innerHTML = reverseLookupMode(this.mode);
  if (typeof (this.canvas) == "undefined") return;
  if (AutoComplete_isVisible()) return;
  if (this.messageIsOpen) return;
  for (var marker in this.markers)
    if (this.markers[marker].elements.input.htmlObject.style.visibility == "visible")
    return;
  if (this.mode != MarkerConsts.IDLE) return;
  if ((tempX >= this.canvasPos.left) &&
      (tempX <= this.canvasPos.left + this.canvasWidth) &&
      (tempY >= this.canvasPos.top) &&
      (tempY <= this.canvasPos.top + this.canvasHeight + 30)) {
    // mouse over canvas
    if (!this.canvasVisible) {
      this.canvas.style.display = "block";
      this.canvasVisible = true;
    }
  } else {
    if (this.canvasVisible) {
      this.mode = MarkerConsts.IDLE;
      this.canvas.style.display = "none";
      this.canvasVisible = false;
    }
  }
}

MarkerController.prototype.keydown = function(e) {
  if (!e) e = window.event
  if (AutoComplete_isVisible())
    return AutoComplete_KeyDown(e);
  else {
    return this.tempMarker.elements.input.keydown(e);
  }
}

MarkerController.prototype.mouseToLocal = function() {
  try {
    var curLeft = tempX - this.canvasPos.left;
  } catch (e) {
    //debugger;
  }
  var curTop = tempY - this.canvasPos.top;
  if (isIE) {
    curLeft -= 2;
    curTop -= 2;
  }
  curTop += $get("AssetPage_container").scrollTop;
  return { left: curLeft, top: curTop };
}

MarkerController.prototype.openMessage = function(messageType) {
  var curPos, curLeft, curTop, curFocus;
  var curText, curSplit;
  this.messageIsOpen = true;
  this.msgBoxType = messageType;
  this.msgBox = $get("AssetPage_Marker_msg");
  $get("AssetPage_Marker_person_msg_email").value = "";
  $get("AssetPage_Marker_imagenote_text").innerHTML = "";
  switch(this.msgBoxType){
    case MarkerConsts.PERSON_MESSAGE:
      $get("AssetPage_Marker_imagenote_msg").style.display = "none";
      $get("AssetPage_Marker_imagenote_text").innerHTML = "";
      this.subMsgBox = $get("AssetPage_Marker_person_msg");
      curFocus = $get("AssetPage_Marker_person_msg_email");
      break;
    case MarkerConsts.NOTE_MESSAGE:
      $get("AssetPage_Marker_person_msg").style.display = "none";
      this.subMsgBox = $get("AssetPage_Marker_imagenote_msg");
      $get("AssetPage_Marker_imagenote_text").innerHTML = this.tempMarker.elements.input.inputObject.value;
      curFocus = $get("AssetPage_Marker_imagenote_text");
      break;
  }
  this.tempMarker.elements.input.okButton.disabled = true;
  this.tempMarker.elements.input.cancelButton.disabled = true;
  this.tempMarker.elements.input.inputObject.disabled = true;
  curPos = MarkerGetPos($get("AssetPage_player_container"));
  this.msgBox.style.display = "block";
  this.subMsgBox.style.display = "block";
  curFocus.focus();
  curLeft = Math.floor((this.canvasWidth - this.msgBox.offsetWidth) / 2);
  if (curLeft < 0) curLeft = 0;
  curTop = Math.floor((this.canvasHeight - this.msgBox.offsetHeight) / 2);
  if (curTop < 0) curTop = 0;
  this.msgBox.style.left = curPos.left + curLeft + "px";
  this.msgBox.style.top = curPos.top + curTop + "px";
  return false;
}

MarkerController.prototype.closeMessage = function(andSave) {
  this.tempMarker.elements.input.okButton.disabled = false;
  this.tempMarker.elements.input.cancelButton.disabled = false;
  this.tempMarker.elements.input.inputObject.disabled = false; 
  this.tempMarker.elements.input.inputObject.focus(); 
  this.msgBox.style.display = "none";
  this.messageIsOpen = false;
}

MarkerController.prototype.openNoteMessage = function() {
  this.openMessage(MarkerConsts.NOTE_MESSAGE);
}

MarkerController.prototype.openPersonMessage = function() {
  this.openMessage(MarkerConsts.PERSON_MESSAGE);
}

MarkerController.prototype.cancelMarker = function(markerID) {
  if (markerID != undefined)
    this.tempMarker = this.markers[markerID];
  if (confirm("Remove marker?"))
    this.removeMarker();
}

MarkerController.prototype.cancelInput = function() {
  // small cancel button clicked
  if (this.tempMarker.elements.notation.text == "") {
    this.removeMarker();
  } else {
    // marker already has notation:
    this.tempMarker.setNotation(this.tempMarker.elements.notation.text);
  }
  return false;
}

MarkerController.prototype.getDefaultMarkerPos = function() {
  var curLeft, curTop, curWidth, curHeight;
  curWidth = Math.min(this.canvasWidth, MarkerConsts.DEFAULT_WIDTH);
  curHeight = Math.min(this.canvasHeight, MarkerConsts.DEFAULT_HEIGHT);
  curLeft = Math.floor((this.canvasWidth - curWidth) / 2);
  curTop = Math.floor((this.canvasHeight - curHeight) / 2);
  if (curLeft < 0) curLeft = 0;
  if (curTop < 0) curTop = 0;
  return ({left: curLeft, top: curTop, width: curWidth, height: curHeight});
}

MarkerController.prototype.addDefaultMarker = function(type) {
  if (AutoComplete_isVisible()) return;
  if (this.messageIsOpen) return;
  if (!this.canvasVisible) return true;
  if (this.mode == MarkerConsts.IDLE) {
    var pos = this.getDefaultMarkerPos();
    if (this.tempMarker != null) {
      if (this.tempMarker.elements.notation.text == "") {
        this.removeElement(this.tempMarker.id);
        this.tempMarker = null;
      }
    }
    this.selectNone();
    this.addSingleMarker(pos, { CanUpdate: true, CanDelete: true });
    this.mode = MarkerConsts.HOVER_INPUT;
  }
}

MarkerController.prototype.addSingleMarker = function(pos, data) {
  this.tempMarker = new Marker(this, this.markerCount++);
  this.tempMarker.data = data;
  this.markers[this.tempMarker.id] = this.tempMarker;
  this.redraw();
  this.tempMarker.left = pos.left;
  this.tempMarker.top = pos.top;
  this.tempMarker.elements.container.setStyleValue("left", pos.left);
  this.tempMarker.elements.container.setStyleValue("top", pos.top);
  this.tempMarker.elements.outerRect.setStyleValue("width", pos.width);
  this.tempMarker.elements.outerRect.setStyleValue("height", pos.height);
  this.tempMarker.elements.innerRect.setStyleValue("width", pos.width - 2);
  this.tempMarker.elements.innerRect.setStyleValue("height", pos.height - 2);
  this.tempMarker.stopResize();
  if (!data.CanUpdate) {
    this.tempMarker.elements.handle.setStyleValue("display", "none");
  }
  if (!data.CanDelete) {
    this.tempMarker.elements.close.setStyleValue("display", "none");
  }
}

MarkerController.prototype.addMarker = function(data) {
  var pos = new Object();
  pos.left = Math.floor(data.Left * this.canvasWidth);
  if (pos.left < 0) pos.left = 0;
  if (pos.left > (this.canvasWidth - 30)) pos.left = this.canvasWidth - 30;
  pos.top = Math.floor(data.Top * this.canvasHeight);
  if (pos.top < 0) pos.top = 0;
  if (pos.top > (this.canvasHeight - 30)) pos.top = this.canvasHeight - 30;
  pos.width = Math.floor(data.Width * this.canvasWidth);
  if (pos.width < 30) pos.width = 30;
  pos.height = Math.floor(data.Height * this.canvasHeight);
  if (pos.height < 30) pos.width = 30;
  this.addSingleMarker(pos, data);
  if (data.MarkedUserID == 0)
    this.tempMarker.setNotation(data.Note);
  else
    this.tempMarker.setNotation(data.MarkedUserName);
}

MarkerController.prototype.queueMarkers = function(markerType, data) {
  switch (markerType) {
    case MarkerConsts.PERSON_MARKER:
      this.personMarkersCueue = data;
      break;
    case MarkerConsts.IMAGE_NOTE:
      this.imageNotesCueue = data;
      break;
  }
  if (this.canvas != undefined)
    this.setCueuedMarkers();
}

MarkerController.prototype.setCueuedMarkers = function() {
  var i, curMarker;
  if (this.personMarkersCueue != undefined) {
    this.canvas.style.display = "block";
    this.canvasVisible = true;
    for (i = 0; i < this.personMarkersCueue.length; i++)
      this.addMarker(this.personMarkersCueue[i]);
    for (curMarker in this.markers) {
      this.markers[curMarker].setNotation(this.markers[curMarker].elements.notation.text);
      this.markers[curMarker].focus(false);
    }
    delete(this.personMarkersCueue);
  }
}

MarkerController.prototype.restoreMouseOverInterval = function(){
  try {
    if (this.canvasVisible && !this.mouseOverInterval)
      this.mouseOverInterval = setInterval(ContextDelegate(this, this.checkMouseOver), 100);
  } catch (e) {
    // ignore
  }
}

MarkerController.prototype.addImageNote = function() {

}

MarkerController.prototype.hideCanvas = function() {
  if (this.canvas == undefined) return;
  if (this.mouseOverInterval) {
    clearInterval(this.mouseOverInterval);
    this.mouseOverInterval = null;
  }
  this.canvas.style.display = "none";
}

MarkerController.prototype.showCanvas = function() {
  if (this.canvas == undefined) return;
  this.canvas.style.display = this.canvasVisible ? "block" : "none";
  this.mouseOverInterval = setInterval(ContextDelegate(this, this.checkMouseOver), 100);
}

MarkerController.prototype.setImageNoteFromInput = function() {
  // user entered text and confirmed - not a person from contact cloud.
  var notation = this.tempMarker.elements.input.inputObject.value;
  this.tempMarker.setNotation(notation);
  this.tempMarker.data.MarkedUserID = 0;
  this.tempMarker.data.Note = notation;
  var percentagePos = this.tempMarker.rectToPercentage();
  var params = new Array(
    { name: "Note", value: escape(this.tempMarker.data.Note) },
    { name: "Left", value: percentagePos.left },
    { name: "Top", value: percentagePos.top },
    { name: "Width", value: percentagePos.width },
    { name: "Height", value: percentagePos.height },
    { name: "SerType", value: 2 });
  if (this.tempMarker.data.ID == undefined) {
    // new marker
    assetPage.message.setTemplateMessage("processing");
    params.push({ name: "AssetID", value: this.tempMarker.controller.assetID });
    params.push({ name: "Owner", value: assetPage.assetData.OwnerID });
    params.push({ name: "TempID", value: this.tempMarker.id });
    executeWebRequest("Assets.AddMarker", params, { onSuccessFunction: newMarkerSuccess, onFailureFunction: markersResultFail });
  } else {
    // updated marker
    assetPage.message.setTemplateMessage("processing");
    params.push({ name: "MarkerID", value: this.tempMarker.data.ID });
    executeWebRequest("Assets.UpdateMarker", params, { onSuccessFunction: updateMarkerSuccess, onFailureFunction: markersResultFail });
  }
  this.tempMarker.userID = "";
  return false;
}

MarkerController.prototype.confirmMarker = function(receivedData) {
  var tempID = receivedData.TempID;
  if (this.markers[tempID] != undefined) {
    this.markers[tempID].data.ID = receivedData.ID;
    assetPage.markerUpdated('new', this.markers[tempID].data);
  }
}

MarkerController.prototype.pageScroll = function() {
  if (isIE) {
    // stupid IE issue..
    if (this.canvasVisible) {
      this.canvas.style.display = "none";
      this.canvas.style.display = "block";
    }
  }
}

// MarkerController [end]

// Marker [start]

function Marker(controller, id) {
  this.controller = controller;
  this.canvas = this.controller.canvas;
  this.canvasHtml = new Object;
  this.data = new Object();
  this.id = id;
  this.outerRectID = "Marker_outer_" + id;
  this.innerRectID = "Marker_inner_" + id;
  this.handleID = "Marker_handle_" + id;
  this.closeID = "Marker_close_" + id;
  this.onCanvas = false;
  this.elements = {
  container: new MarkerContainer(this, "container", id),
  outerRect: new MarkerOuter(this, "outer", id, new MarkerCssObject()),
  innerRect: new MarkerInner(this, "inner", id, new MarkerCssObject()),
  handle: new MarkerHandle(this, "handle", id, new MarkerCssObject()),
  close: new MarkerClose(this, "close", id, new MarkerCssObject()),
  notation: new MarkerNotation(this, "notation", id, new MarkerCssObject()),
  input: new MarkerInput(this, "input", id, new MarkerCssObject())
  }
  this.inFocus = true;
  this.inHover = false;
}

Marker.prototype.start = function() {
  var mouseLocal = this.controller.mouseToLocal();
  this.left = mouseLocal.left;
  this.top = mouseLocal.top;
}

Marker.prototype.getHtml = function() {  
  var curHtml = this.elements.container.getHtml();
  for (var prop in this.elements) {
    if (prop != "container")
      curHtml.appendChild(this.elements[prop].getHtml());
  }
  return curHtml;
}

Marker.prototype.setHtmlObjects = function() {
  for (var prop in this.elements){
    this.elements[prop].setHtmlObject();
  }
  this.elements.input.setHtmlInput();
}

Marker.prototype.startResize = function() {
var mouseLocal = this.controller.mouseToLocal();
  var curLeft = Math.min(this.left, mouseLocal.left);
  if (curLeft <= 0) curLeft = 0;
  var curTop = Math.min(this.top, mouseLocal.top);
  if (curTop <= 0) curTop = 0;
  var curWidth = Math.abs(Math.max(mouseLocal.left, curLeft) - this.left);
  var curHeight = Math.abs(Math.max(mouseLocal.top, curTop) - this.top);
  if ((curLeft + curWidth) > this.controller.canvasWidth)
    curWidth = this.controller.canvasWidth - curLeft;
  if ((curTop + curHeight) > this.controller.canvasHeight)
    curHeight = this.controller.canvasHeight - curTop;
  this.elements.container.setStyleValue("left", curLeft);
  this.elements.container.setStyleValue("top", curTop);
  this.elements.outerRect.resizeTo(0, 0, curWidth, curHeight);
  this.elements.innerRect.resizeTo(1, 1, curWidth - 2, curHeight - 2);
}

Marker.prototype.stopResize = function() {
  if (this.elements.outerRect.htmlObject.offsetWidth < MarkerConsts.MIN_SIZE ||
      this.elements.outerRect.htmlObject.offsetHeight < MarkerConsts.MIN_SIZE) {
    this.controller.removeElement(this.id);
    this.tempMarker = null;
    return;
  }
  this.left = parseInt(this.elements.container.htmlObject.style.left);
  this.top = parseInt(this.elements.container.htmlObject.style.top);
  this.placeHandle();
  this.placeClose();
  this.elements.notation.setText("");
  this.placeNotation();
  this.placeInput();
  this.elements.notation.setStyleValue("visibility", "hidden");
  this.elements.input.setStyleValue("visibility", "visible");
  AutoComplete_Attach(this.elements.input);
  $get(this.elements.input.id + "_inp").focus();
}

Marker.prototype.placeHandle = function() {
  var handleLeft = this.elements.outerRect.htmlObject.offsetWidth - 14;
  var handleTop = this.elements.outerRect.htmlObject.offsetHeight - 14;
  this.elements.handle.resizeTo(handleLeft, handleTop, 12, 12);
  this.elements.handle.setStyleValue("display", "block");
  this.elements.close.setStyleValue("backgroundRepeat", "no-repeat");
}

Marker.prototype.placeClose = function() {
  var closeLeft = this.elements.outerRect.htmlObject.offsetWidth - 11;
  this.elements.close.resizeTo(closeLeft, 2, 9, 9);
  this.elements.close.setStyleValue("display", "block");
  this.elements.close.setStyleValue("backgroundRepeat", "no-repeat");
}

Marker.prototype.placeNotation = function() {
  // by default, notation is 100*18 rect
  var offsetLeft = (this.elements.outerRect.htmlObject.offsetWidth - this.elements.notation.width) / 2;
  offsetLeft = Math.floor(offsetLeft);
  /*if (this.elements.notation.width > this.canvasWidth){
  curLeft = 0;
  } else if (curLeft < 0) {
  curLeft = 0;
  } else if (curLeft + this.elements.notation.width > this.canvasWidth){
  curLeft = this.canvasWidth - this.elements.notation.width;
  }*/
  //if (!isIE)curLeft += MarkerConsts.NOTATION_PADDING;
  var rectHeight = this.elements.outerRect.htmlObject.offsetHeight;
  var curTop;
  if (this.top + rectHeight + 22 > this.controller.canvasHeight)
    curTop = -22;
  else
    curTop = this.elements.outerRect.htmlObject.offsetHeight;
  this.elements.notation.moveTo(offsetLeft, curTop);
  this.elements.notation.setStyleValue("display", "block");
}

Marker.prototype.placeInput = function() {
  var curLeft = this.elements.notation.left;
  var curTop = this.elements.notation.top;
  var inputWidth = this.elements.notation.width;
  inputWidth -= MarkerConsts.NOTATION_PADDING * 2;
  if (!isIE)
    inputWidth -= MarkerConsts.NOTATION_PADDING * 2;
  this.elements.input.inputObject.style.width = inputWidth + "px";
  this.elements.input.moveTo(curLeft, curTop);
}

Marker.prototype.hoverIn = function(elementType) {
  canUpdate = (this.data.CanUpdate == undefined || this.data.CanUpdate == true);
  canDelete = (this.data.CanDelete == undefined || this.data.CanDelete == true);
  if (this.inFocus) {
    switch (elementType) {
      case "close":
        this.elements.close.setStyleValue("backgroundPosition", "-9px 0px");
        break;
      case "input":
        this.controller.mode = MarkerConsts.HOVER_INPUT;
        break;
      case "notation":
        this.controller.mode = MarkerConsts.HOVER_NOTATION;
        break;
    }
    return;
  }
  if (this.inHover) return;
  this.inHover = canUpdate;
  if (canUpdate) {
    this.elements.outerRect.setStyleValue("border", "2px solid #ffffff");
    this.elements.outerRect.setStyleValue("left", this.elements.outerRect.styleObject.left[0] - 1);
    this.elements.outerRect.setStyleValue("top", this.elements.outerRect.styleObject.top[0] - 1);
    this.elements.innerRect.setStyleValue("border", "2px solid #000000");
    this.elements.innerRect.setStyleValue("width", this.elements.innerRect.styleObject.width[0] - 2);
    this.elements.innerRect.setStyleValue("height", this.elements.innerRect.styleObject.height[0] - 2);
    this.elements.handle.setStyleValue("display", "block");
    this.elements.handle.setStyleValue("backgroundPosition", "-13px 0px");
    this.elements.close.setStyleValue("left", this.elements.close.styleObject.left[0] - 1);
    this.elements.close.setStyleValue("top", this.elements.close.styleObject.top[0] + 1);
  }
  if (canDelete) {
    this.elements.close.setStyleValue("display", "block");
  }

  switch (elementType) {
    case "close":
      this.elements.close.setStyleValue("backgroundPosition", "-27px 0px");
      break;
    default:
      this.elements.close.setStyleValue("backgroundPosition", "-18px 0px");
      break;
  }
}

Marker.prototype.hoverOut = function(elementType) {
  canUpdate = (this.data.CanUpdate != undefined && this.data.CanUpdate == true);
  canDelete = (this.data.CanDelete != undefined && this.data.CanDelete == true);
  if (this.inFocus) {
    switch (elementType) {
      case "close":
        this.elements.close.setStyleValue("backgroundPosition", "0px 0px");
        return;
      case "notation":
        if (this.controller.mode == MarkerConsts.HOVER_NOTATION)
          this.controller.mode = MarkerConsts.IDLE;
        break;
      case "input":
        break;
    }
    return;
  }
  this.elements.close.setStyleValue("display", "none");
  this.elements.close.setStyleValue("backgroundPosition", "0px 0px");
  if (!this.inHover) return;
  this.inHover = false;
  this.elements.outerRect.setStyleValue("border", "1px solid #ffffff");
  this.elements.outerRect.setStyleValue("left", this.elements.outerRect.styleObject.left[0] + 1);
  this.elements.outerRect.setStyleValue("top", this.elements.outerRect.styleObject.top[0] + 1);
  this.elements.innerRect.setStyleValue("border", "1px solid #000000");
  this.elements.innerRect.setStyleValue("width", this.elements.innerRect.styleObject.width[0] + 2);
  this.elements.innerRect.setStyleValue("height", this.elements.innerRect.styleObject.height[0] + 2);
  this.elements.handle.setStyleValue("display", "none");
  this.elements.handle.setStyleValue("backgroundPosition", "0px 0px");
  this.elements.close.setStyleValue("left", this.elements.close.styleObject.left[0] + 1);
  this.elements.close.setStyleValue("top", this.elements.close.styleObject.top[0] - 1);
}

Marker.prototype.focus = function(focus) {
  if (this.inHover) this.hoverOut();
  this.elements.outerRect.setStyleValue("border", focus ? "1px solid #fdf983" : "1px solid #ffffff");
  this.elements.handle.setStyleValue("display", focus ? "block" : "none");
  this.elements.close.setStyleValue("display", focus ? "block" : "none");
  this.elements.notation.setStyleValue("visibility", "visible");
  this.elements.input.setStyleValue("visibility", "hidden");
  //this.placeClose();
  this.inFocus = focus;
}

Marker.prototype.startDrag = function() {
  this.elements.outerRect.setStyleValue("cursor", "move");
  this.elements.innerRect.setStyleValue("cursor", "move");
}

Marker.prototype.dragTo = function(left, top) {
  if ((left + this.elements.outerRect.htmlObject.offsetWidth) > this.controller.canvasWidth)
    left = this.controller.canvasWidth - this.elements.outerRect.htmlObject.offsetWidth;
  if ((top + this.elements.outerRect.htmlObject.offsetHeight) > this.controller.canvasHeight)
    top = this.controller.canvasHeight - this.elements.outerRect.htmlObject.offsetHeight;
  if (left <= 0)
    left = 0;
  if (top <= 0)
    top = 0;
  this.left = left;
  this.top = top;
  this.elements.container.setStyleValue("left", left);
  this.elements.container.setStyleValue("top", top);
  this.placeHandle();
  this.placeClose();
  this.placeNotation();
  this.placeInput();
}

Marker.prototype.handleResize = function(left, top) {
  var curWidth = left + 12 - this.left;
  var curHeight = top + 12 - this.top;
  if (curWidth < MarkerConsts.MIN_SIZE) curWidth = MarkerConsts.MIN_SIZE;
  if (curHeight < MarkerConsts.MIN_SIZE) curHeight = MarkerConsts.MIN_SIZE;
  if ((this.left + curWidth) >= this.controller.canvasWidth)
    curWidth = this.controller.canvasWidth - this.left;
  if ((this.top + curHeight) >= this.controller.canvasHeight)
    curHeight = this.controller.canvasHeight - this.top;
  this.elements.handle.setStyleValue("left", curWidth - 12);
  this.elements.handle.setStyleValue("top", curHeight - 12);
  this.elements.outerRect.resizeTo(0, 0, curWidth, curHeight);
  this.elements.innerRect.resizeTo(1, 1, curWidth - 2, curHeight - 2);
  this.placeClose();
  this.placeNotation();
  this.placeInput();
}

Marker.prototype.stopDrag = function() {
  this.elements.outerRect.setStyleValue("cursor", "default");
  this.elements.innerRect.setStyleValue("cursor", "default");
}

Marker.prototype.setNotation = function(curText) {
  this.elements.notation.setText(curText);
  this.elements.notation.htmlObject.style.visibility = "visible";
  this.elements.input.htmlObject.style.visibility = "hidden"; 
  this.controller.mode = MarkerConsts.IDLE;
}


Marker.prototype.rectToPercentage = function() {
var left = parseInt(this.elements.container.htmlObject.style.left) / this.controller.canvasWidth;
  var top = parseInt(this.elements.container.htmlObject.style.top) / this.controller.canvasHeight;
  var width = this.elements.outerRect.htmlObject.offsetWidth / this.controller.canvasWidth;
  var height = this.elements.outerRect.htmlObject.offsetHeight / this.controller.canvasHeight;
  return { left: left, top: top, width: width, height: height };
}

// Marker [end]

// Element [start]

function MarkerElement(container, type, id, styleObject) {
  this.container = container;
  this.type = type;
  this.id = "Marker_" + type + "_" + id;
  this.styleObject = styleObject;
}

MarkerElement.prototype.getHtml = function() {
  var curHtml = document.createElement("div");
  curHtml.setAttribute("id", this.id);
  curHtml.setAttribute("container_id", this.container.id);
  curHtml.setAttribute("element_type", this.type);
  curHtml.onmouseover = function() { markerController.hoverIn(this.getAttribute("container_id"), this.getAttribute("element_type")) };
  curHtml.onmouseout = function() { markerController.hoverOut(this.getAttribute("container_id"), this.getAttribute("element_type")) };
  curHtml.onmousedown = function() { markerController.startDrag(this.getAttribute("container_id"), this.getAttribute("element_type")) };
  for (prop in this.styleObject) {
    curHtml.style[prop] = this.styleObject[prop][0] + this.styleObject[prop][1]
  }
  return curHtml;
}

MarkerElement.prototype.resizeTo = function(left, top, width, height) {
  this.setStyleValue("left", left);
  this.setStyleValue("top", top);
  this.setStyleValue("width", width);
  this.setStyleValue("height", height);
  this.left = left;
  this.top = top;
}

MarkerElement.prototype.moveTo = function(left, top) {
  this.setStyleValue("left", left);
  this.setStyleValue("top", top);
  this.left = left;
  this.top = top;
}

MarkerElement.prototype.setHtmlObject = function() {
  this.htmlObject = $get(this.id);
}

MarkerElement.prototype.setStyleValue = function(param, value) {
  if (typeof(this.styleObject[param]) == "undefined"){
    // new param
    this.styleObject[param] = [value, ""];
  }
  this.styleObject[param][0] = value;
  this.htmlObject.style[param] = this.styleObject[param][0] + this.styleObject[param][1];
}
// Element [end]

// container [start]

function MarkerContainer(container, type, id) {
  var styleObject = {
    position: ["relative", ""],
    left: [0, "px"],
    top: [0, "px"],
    cursor: ["default", ""]
  }
  this.constructor(container, type, id, styleObject);
  this.styleObject.background = ["url(/Images/null.gif)", ""];
}
MarkerContainer.prototype = new MarkerElement();
MarkerContainer.prototype.constructor = MarkerElement;

MarkerContainer.prototype.getHtml = function() {
  var curHtml = document.createElement("div");
  curHtml.setAttribute("id", this.id);
  for (prop in this.styleObject)
    curHtml.style[prop] = this.styleObject[prop][0] + this.styleObject[prop][1];
  return curHtml;
}

// outer [end]

// outer rect [start]

function MarkerOuter(container, type, id, styleObject) {
  this.constructor(container, type, id, styleObject);
  this.styleObject.border = ["1px solid #fdf983", ""];
  this.styleObject.background = ["url(/Images/null.gif)", ""];
}
MarkerOuter.prototype = new MarkerElement();
MarkerOuter.prototype.constructor = MarkerElement;

// outer rect [end]

// inner rect [start]

function MarkerInner(container, type, id, styleObject) {
  this.constructor(container, type, id, styleObject);
  this.styleObject.left[0] += 1;
  this.styleObject.top[0] += 1;
  this.styleObject.width[0] -= 2;
  this.styleObject.height[0] -= 2;
  this.styleObject.border = ["1px solid #000000", ""];
}
MarkerInner.prototype = new MarkerElement();
MarkerInner.prototype.constructor = MarkerElement;

// inner rect [end]

// marker icon [start]

function MarkerIcon(container, type, id, styleObject) {
  this.constructor(container, type, id, styleObject);
  this.styleObject.left[0] += 2;
  this.styleObject.top[0] += 2;
  this.styleObject.width[0] -= 2;
  this.styleObject.height[0] -= 2;
  this.styleObject.border = ["1px solid #000000", ""];
}
MarkerIcon.prototype = new MarkerElement();
MarkerIcon.prototype.constructor = MarkerElement;

// marker icon [end]

// handle [start]

function MarkerHandle(container, type, id, styleObject) {
  this.constructor(container, type, id, styleObject);
  this.styleObject.width[0] = 12;
  this.styleObject.height[0] = 12;
  this.styleObject.display = ["none", ""];
  this.styleObject.backgroundImage = ["url(/Images/AssetPage/MarkerResizeHandle.png)", ""];
  this.styleObject.backgroundRepeat = ["no-repeat", ""];
  this.styleObject.cursor = ["se-resize", ""];
}
MarkerHandle.prototype = new MarkerElement();
MarkerHandle.prototype.constructor = MarkerElement;

// handle [end]

// close [start]

function MarkerClose(container, type, id, styleObject){
  this.constructor(container, type, id, styleObject);
  this.styleObject.width[0] = 9;
  this.styleObject.height[0] = 9;
  this.styleObject.display = ["none", ""];
  this.styleObject.background = ["url(/Images/AssetPage/MarkerClose.png) no-repeat", ""];
  this.styleObject.cursor = ["pointer", ""];
}
MarkerClose.prototype = new MarkerElement();
MarkerClose.prototype.constructor = MarkerElement;

MarkerClose.prototype.getHtml = function() {
  var curHtml = MarkerElement.prototype.getHtml.call(this);
  curHtml.onmouseup = null;
  curHtml.onmousedown = function() {
    markerController.canvas.onmousedown = null;
    markerController.cancelMarker(this.getAttribute("container_id"));
    setTimeout(function() { markerController.canvas.onmousedown = function() { markerController.mouseDown() } }, 100);
  };
  return curHtml;
}


// close [end]

//  notation [start]

function MarkerNotation(container, type, id, styleObject) {
  this.constructor(container, type, id, styleObject);
  this.styleObject.width[0] = MarkerConsts.NOTATION_WIDTH;
  this.styleObject.height[0] = MarkerConsts.NOTATION_HEIGHT;
  if (isIE)
    this.styleObject.height[0] += MarkerConsts.NOTATION_PADDING * 2; 
  this.styleObject.visibility = ["hidden", ""];
  this.styleObject.cursor = ["text", ""];
  this.styleObject.background = ["url(/Images/AssetPage/MarkerTextBG.png)", ""];
  this.styleObject.padding = [MarkerConsts.NOTATION_PADDING, "px"];
  this.styleObject.color = ["#000000", ""];
  this.styleObject.whiteSpace = ["nowrap", ""];
  this.styleObject.fontFamily = ["Verdana, Arial, Helvetica", ""];
  this.styleObject.textAlign = ["center", ""];
  this.styleObject.fontSize = [12, "px"];
  this.styleObject.fontWeight = ["bold", ""];
  this.styleObject.MozUserSelect = ["none", ""];
  this.width = MarkerConsts.NOTATION_WIDTH;
  this.height = MarkerConsts.NOTATION_HEIGHT;
  this.text = "";
  if (!isIE){
    this.width += MarkerConsts.NOTATION_PADDING * 2;
    this.height += MarkerConsts.NOTATION_PADDING * 2;
  }
}
MarkerNotation.prototype = new MarkerElement();
MarkerNotation.prototype.constructor = MarkerElement;

MarkerNotation.prototype.setText = function(curText) {
  if (typeof(this.htmlObject) == "object"){
    this.text = curText;
    this.htmlObject.innerHTML = curText;
    this.htmlObject.style.width = "";
    var requiredWidth = MarkerConsts.NOTATION_WIDTH;
    if (!isIE) requiredWidth += MarkerConsts.NOTATION_PADDING * 2;
    if (this.htmlObject.offsetWidth < requiredWidth)
      this.htmlObject.style.width = MarkerConsts.NOTATION_WIDTH + "px";
    this.width = this.htmlObject.offsetWidth;
    if (!isIE)
      this.width -= MarkerConsts.NOTATION_PADDING * 2;
    if (this.width != requiredWidth){
      this.styleObject.width = ["", ""];
      this.container.placeNotation();
    }
    if (!isIE)
      this.width += MarkerConsts.NOTATION_PADDING * 2;
    this.styleObject.width[0] = this.width;
    if (this.styleObject.width[0] != "")
      this.styleObject.width[1] = "px";
    var pos = MarkerGetPos(this.htmlObject);
    this.left = pos.left;
    this.top = pos.top;
  }
}

MarkerNotation.prototype.getHtml = function() {
  var curHtml = document.createElement("div");
  curHtml.setAttribute("id", this.id);
  curHtml.setAttribute("container_id", this.container.id);
  curHtml.setAttribute("element_type", this.type);
  curHtml.onmouseover = function() { markerController.hoverIn(this.getAttribute("container_id"), this.getAttribute("element_type")) };
  curHtml.onmouseout = function() { markerController.hoverOut(this.getAttribute("container_id"), this.getAttribute("element_type")) };
  curHtml.onmousedown = function() { markerController.startDrag(this.getAttribute("container_id"), this.getAttribute("element_type")) };
  curHtml.onselectstart = function() { return false };

  for (prop in this.styleObject) {
    curHtml.style[prop] = this.styleObject[prop][0] + this.styleObject[prop][1]
  }
  return curHtml;
}
// notation [end]

//  input [start]

function MarkerInput(container, type, id, styleObject) {
  this.constructor(container, type, id, styleObject);
  this.styleObject.width[0] = 150;
  this.styleObject.height[0] = 22;
  this.styleObject.visibility = ["hidden", ""];
  this.styleObject.background = ["url(/Images/AssetPage/MarkerTextBG.png)", ""];
  this.styleObject.padding = [3, "px"];
  this.autocompleteIsOpen = false;
  this.width = MarkerConsts.NOTATION_WIDTH;
  if (!isIE){
    this.width += MarkerConsts.NOTATION_PADDING * 2;
  }
  this.text = "";
}
MarkerInput.prototype = new MarkerElement();
MarkerInput.prototype.constructor = MarkerElement;

MarkerInput.prototype.setHtmlInput = function() {
  this.htmlObject.appendChild(this.getInputHtml());
  var buttons = this.getButtonsHtml();
  this.htmlObject.appendChild(buttons[0]);
  this.htmlObject.appendChild(buttons[1]);
  this.inputObject = $get(this.id + "_inp");
  this.okButton = $get(this.id + "_ok");
  this.cancelButton = $get(this.id + "_cancel");
}

MarkerInput.prototype.setText = function(curText) {
  this.text = curText;
  this.inputObject.value = curText;
}

MarkerInput.prototype.selectedAutocomplete = function(id, name) {
  this.container.setNotation(name);
  var percentagePos = this.container.rectToPercentage();
  this.container.data.MarkedUserID = id;
  this.container.data.Note = "";
  var params = new Array(
    { name: "MarkedUserID", value: id },
    { name: "Note", value: "" },
    { name: "Left", value: percentagePos.left },
    { name: "Top", value: percentagePos.top },
    { name: "Width", value: percentagePos.width },
    { name: "Height", value: percentagePos.height },
    { name: "SerType", value: 2 });
  if (this.container.data.ID == undefined) {
    // new marker
    params.push({ name: "AssetID", value: this.container.controller.assetID });
    params.push({ name: "Owner", value: assetPage.assetData.OwnerID });
    params.push({ name: "TempID", value: this.container.id });
    executeWebRequest("Assets.AddMarker", params, { onSuccessFunction: newMarkerSuccess, onFailureFunction: markersResultFail });
  } else {
    // updated marker
    params.push({ name: "MarkerID", value: this.container.data.ID });
    executeWebRequest("Assets.UpdateMarker", params, { onSuccessFunction: updateMarkerSuccess, onFailureFunction: markersResultFail });
  }
  assetPage.message.setTemplateMessage("processing");
  this.container.userID = id;
}

MarkerInput.prototype.getInputHtml = function() {
  var inputWidth = MarkerConsts.NOTATION_WIDTH - MarkerConsts.NOTATION_PADDING * 2;
  var curHtml = document.createElement("input");
  curHtml.setAttribute("id", this.id + "_inp");
  curHtml.style.width = inputWidth + "px";
  curHtml.style.height = "16px";
  curHtml.style.fontSize = "11px";
  curHtml.onkeydown = function(event) { return markerController.keydown(event) };
  curHtml.value = this.text;
  return curHtml;
}

MarkerInput.prototype.getButtonsHtml = function() {
  var okButton = document.createElement("button");
  okButton.onclick = function() { markerController.setImageNoteFromInput() };
  okButton.setAttribute("id", this.id + "_ok");
  okButton.setAttribute("type", "button");
  okButton.className = "AssetPage_Marker_okay_button";
  okButton.innerHTML = "OK";
  
  var cancelButton = document.createElement("button");
  cancelButton.onclick = function() { markerController.cancelInput() };
  cancelButton.setAttribute("id", this.id + "_cancel");
  cancelButton.setAttribute("type", "button");
  cancelButton.className = "AssetPage_Marker_cancel_button";
  cancelButton.innerHTML = "Cancel";
  return [okButton, cancelButton];
}

MarkerInput.prototype.keydown = function(e) {
  var keynum = isIE ? e.keyCode : e.which;
  switch (keynum) {
    case 13: case 9: // return;
      this.container.controller.setImageNoteFromInput();
      //this.container.controller.openMessage(MarkerConsts.PERSON_MESSAGE);
      return false;
      break;
    case 27: // escape
      return false;
      break;
  }
  return true;
}

MarkerInput.prototype.setAutocompleteIsOpen = function(isOpen) {
  this.autocompleteIsOpen = isOpen;
  if (this.container.controller.canvasVisible){
    if (isOpen) {
      this.container.controller.mode = MarkerConsts.AUTOCOMPLETE;
    } else {
      switch (this.htmlObject.style.visibility){
        case "visible": case "":
          this.container.controller.mode = MarkerConsts.HOVER_INPUT;
          break;
        case "hidden":
           this.container.controller.mode = MarkerConsts.IDLE;
          break;
      }
    }
  } else
    this.container.controller.mode = MarkerConsts.IDLE;
}

// input [end]

// Server Callbacks [start]

function markersResultFail(callbackData) {
  assetPage.message.setMessage("Marker operation failed", false, true, true);
}

function newMarkerSuccess(receivedData, callbackData) {
  assetPage.message.setTemplateMessage("done");
  markerController.confirmMarker(receivedData);
}

function updateMarkerSuccess(receivedData, callbackData) {
  assetPage.message.setTemplateMessage("done");
}

function deleteMarkerSuccess(receivedData, callbackData) {
  assetPage.message.setTemplateMessage("done");
  
}

// Server Callbacks [end]

// Utilities [start]

function MarkerGetPos(obj) {
  var curleft = 0;
  var curtop = 0;
  if (obj == null) return ({ left: 0, top: 0 });
  if (obj.offsetParent == null){
    if (obj.id == "AssetPage_image_player") {
      if (obj.style.display == "") {
        obj.style.display = "block";
      }
    }
  }
  if (obj.offsetParent) {
    while (obj.offsetParent){
      curleft += obj.offsetLeft-obj.scrollLeft;
      curtop += obj.offsetTop-obj.scrollTop;
      var position='';
      if (obj.style&&obj.style.position) position=obj.style.position.toLowerCase();
      if ((position=='absolute')||(position=='relative')) break;
      while (obj.parentNode!=obj.offsetParent) {
        obj=obj.parentNode;
        curleft -= obj.scrollLeft;
        curtop -= obj.scrollTop;
      }
      obj = obj.offsetParent;
    }
  } else {
    if (obj.x)
      curleft += obj.x;
    if (obj.y)
      curtop += obj.y;
  }
  return {left:curleft,top:curtop};
}

function MarkerCssObject() {
  var mouseLocal = markerController.mouseToLocal();
  this.position = ["absolute", ""];
  this.left = [0, "px"];
  this.top = [0, "px"];
  this.width = [3, "px"];
  this.height = [3, "px"];
  this.cursor = ["default", ""];
}
  
// Utilities [end]


// Autocomplete [start]

/**
* © Copyright 2005 Richard Heyes
*/

/**
* Global vars
*/
var __AutoComplete;

/**
* Attachs the autocomplete object to a form element. Sets
* onkeypress event on the form element.
* 
* @param string formElement Name of form element to attach to
* @param array  data        Array of strings of which to use as the autocomplete data
*/
function AutoComplete_Create(data, maxSize)
{
  if (AutoComplete_isVisible()) return;
  __AutoComplete = {'data':            data,
                    'isVisible':       false,
                    'dropdown':        null,
                    'highlighted':     null};

  // Hides the dropdowns when document clicked
  var docClick = function(){
    AutoComplete_HideDropdown();
  }

  if (document.addEventListener) {
    document.addEventListener('click', docClick, false);
  } else if (document.attachEvent) {
      document.attachEvent('onclick', docClick, false);
  }


  // Max number of items shown at once
  __AutoComplete['maxitems'] = maxSize;
  __AutoComplete['firstItemShowing'] = 0;
  __AutoComplete['lastItemShowing']  = maxSize - 1;
  
  // Prevent select dropdowns showing thru
  if (isIE) {
    __AutoComplete['iframe'] = document.createElement('iframe');
    __AutoComplete['iframe'].id = 'AssetPage_marker_iframe';
    __AutoComplete['iframe'].style.position = 'absolute';
    __AutoComplete['iframe'].style.top = '0';
    __AutoComplete['iframe'].style.left = '0';
    __AutoComplete['iframe'].style.width = '0px';
    __AutoComplete['iframe'].style.height = '0px';
    __AutoComplete['iframe'].style.zIndex = '98';
    __AutoComplete['iframe'].style.visibility = 'hidden';
    $get("AssetPage_container").insertBefore(__AutoComplete['iframe'], $get("AssetPage_sub_container"));
  }
}

function AutoComplete_isVisible(){
  toReturn = false;
  if (typeof(__AutoComplete) == "object")
    if (__AutoComplete.dropdown != null)
      toReturn = (__AutoComplete.dropdown.style.visibility == "visible") ;
  return toReturn;
}

/**
* Creates the dropdown layer
*/
function AutoComplete_CreateDropdown()
{
    var curPos = MarkerGetPos(__AutoComplete['element']);
    curPos.left += markerController.canvasPos.left;
    curPos.top += markerController.canvasPos.top + __AutoComplete['element'].offsetHeight;
    var width = __AutoComplete['element'].offsetWidth;

    __AutoComplete['dropdown'] = document.createElement('div');
    __AutoComplete['dropdown'].className = 'AssetPage_autocomplete'; // Don't use setAttribute()

    //$get("AssetPage_container").insertBefore(__AutoComplete['dropdown'], $get("AssetPage_sub_container"));
    $get("AssetPage_container").appendChild(__AutoComplete['dropdown']);
    
    // Position it
    __AutoComplete['dropdown'].style.left       = curPos.left + 'px';
    __AutoComplete['dropdown'].style.top        = curPos.top + 'px';
    __AutoComplete['dropdown'].style.width      = width + 10 + 'px';
    __AutoComplete['dropdown'].style.zIndex     = '99';
    __AutoComplete['dropdown'].style.visibility = 'hidden';
}

/**
/* Attaches the dropdown to an input
*/
function AutoComplete_Attach(fromObject) {
  if (__AutoComplete['fromObject'] != fromObject && __AutoComplete['element'] != undefined) {
    //already attached to another object, detaching:
    __AutoComplete['element'].onkeyup = null;
    __AutoComplete['element'].onkeypress = null;
    __AutoComplete['element'].ondblclick = null;
    __AutoComplete['element'].onclick = null;
  }
  __AutoComplete['fromObject'] = fromObject;
  __AutoComplete['originalKeyDown'] = fromObject.inputObject.onkeydown;  
  __AutoComplete['element'] = fromObject.inputObject;
  __AutoComplete['element'].setAttribute('autocomplete', 'off');
  __AutoComplete['element'].onkeyup    = function(e) {if (!e) e = window.event; return AutoComplete_KeyUp(e);}
  __AutoComplete['element'].onkeypress = function(e) {if (!e) e = window.event; if (e.keyCode == 13 || isOpera) return false;}
  __AutoComplete['element'].ondblclick = function() {AutoComplete_ShowDropdown();}
  __AutoComplete['element'].onclick = function(e) { if (!e) e = window.event; e.cancelBubble = true; e.returnValue = false; }

  if (__AutoComplete['dtopdown'] == undefined)
    AutoComplete_CreateDropdown();
}

/**
* Shows the dropdown layer
*/
function AutoComplete_ShowDropdown()
{
    AutoComplete_HideDropdown();
    var value = __AutoComplete['element'].value.toLowerCase();
    var toDisplay = new Array();
    var newDiv    = null;
    var itemDiv   = new Object(); 
    var sepDiv    = null;
    var numItems  = __AutoComplete['dropdown'].childNodes.length;

    // Remove all child nodes from dropdown
    while (__AutoComplete['dropdown'].childNodes.length > 0) {
        __AutoComplete['dropdown'].removeChild(__AutoComplete['dropdown'].childNodes[0]);
    }

    // Go thru data searching for matches
    for (var i = 0; i < __AutoComplete['data'].length; i++) {
        if (__AutoComplete['data'][i].name.substr(0, value.length).toLowerCase() == value) {
            toDisplay[toDisplay.length] = __AutoComplete['data'][i];
        }
    }
    
    // No matches?
    if (toDisplay.length == 0) {
        AutoComplete_HideDropdown();
        return;
    }

    // Add data to the dropdown layer
    for (i = 0; i < toDisplay.length; i++) {
        newDiv = document.createElement('div');
        newDiv.className = 'AssetPage_autocomplete_item'; // Don't use setAttribute()
        newDiv.setAttribute('id', 'autocomplete_item_' + i);
        newDiv.setAttribute('index', i);
        newDiv.style.zIndex = '99';
        
         // Scrollbars are on display ?
        if (toDisplay.length > __AutoComplete['maxitems'] && navigator.userAgent.indexOf('MSIE') == -1) {
            newDiv.style.width = __AutoComplete['element'].offsetWidth - 22 + 'px';
        }

        newDiv.onmouseover = function() {AutoComplete_HighlightItem(this.getAttribute('index'));};
        newDiv.onclick     = function() {
          AutoComplete_SetValue();
          AutoComplete_HideDropdown();
        }
        
        itemDiv.hidden = document.createElement("input");
        itemDiv.hidden.setAttribute('type', "hidden");
        itemDiv.hidden.setAttribute('value', toDisplay[i].id);
                    
        itemDiv.name = document.createElement("div");
        itemDiv.name.setAttribute('id', 'autocomplete_item_name_' + i);
        itemDiv.name.className = "name";
        if (toDisplay[i].isViewer) itemDiv.name.style.fontWeight = "bold";
        itemDiv.name.style.background = "url('" + toDisplay[i].avatar + "') no-repeat";
        itemDiv.name.style.whiteSpace = "nowrap";
        itemDiv.name.appendChild(document.createTextNode(toDisplay[i].name));
        
        itemDiv.email = document.createElement("div");
        itemDiv.email.className = "email";
        itemDiv.email.appendChild(document.createTextNode(toDisplay[i].email));
        if (i > 0){
          itemDiv.sep = document.createElement("div");
          itemDiv.sep.className = "separator";
          newDiv.appendChild(itemDiv.sep);
        }
        newDiv.appendChild(itemDiv.name);
        newDiv.appendChild(itemDiv.email);
        newDiv.appendChild(itemDiv.hidden);
        
        __AutoComplete['dropdown'].appendChild(newDiv);
    }
    
    
    // Too many items?
    if (toDisplay.length > __AutoComplete['maxitems']) {
        __AutoComplete['dropdown'].style.height = (__AutoComplete['maxitems'] * 34) + 2 + 'px';
    
    } else {
        __AutoComplete['dropdown'].style.height = '';
    }

    
    /**
    * Set left/top in case of document movement/scroll/window resize etc
    */
    var curPos = MarkerGetPos(__AutoComplete['element']);
    curPos.left += markerController.canvasPos.left + parseInt(markerController.tempMarker.elements.container.htmlObject.style.left);
    // deciding if to display the list below or above
    curPos.top += markerController.canvasPos.top + parseInt(markerController.tempMarker.elements.container.htmlObject.style.top) + __AutoComplete['element'].offsetHeight;
    __AutoComplete['dropdown'].style.left = curPos.left + "px";
    __AutoComplete['dropdown'].style.top  = curPos.top + "px";
    //__AutoComplete['dropdown'].style.zIndex = 0;

    // Show the iframe for IE
    if (isIE) {
        __AutoComplete['iframe'].style.top    = __AutoComplete['dropdown'].style.top;
        __AutoComplete['iframe'].style.left   = __AutoComplete['dropdown'].style.left;
        __AutoComplete['iframe'].style.width  = __AutoComplete['dropdown'].offsetWidth;
        __AutoComplete['iframe'].style.height = __AutoComplete['dropdown'].offsetHeight;
        
        __AutoComplete['iframe'].style.visibility = 'visible';
    }


    // Show dropdown
    if (!__AutoComplete['isVisible']) {
        __AutoComplete['dropdown'].style.visibility = 'visible';
        __AutoComplete['isVisible'] = true;
    }

    
    // If now showing less items than before, reset the highlighted value
    if (__AutoComplete['dropdown'].childNodes.length != numItems) {
        __AutoComplete['highlighted'] = null;
    }
    __AutoComplete['fromObject'].setAutocompleteIsOpen(true);
}


/**
* Hides the dropdown layer
*/
function AutoComplete_HideDropdown()
{
  if (!AutoComplete_isVisible()) return;
    if (__AutoComplete['iframe']) {
        __AutoComplete['iframe'].style.visibility = 'hidden';
    }

    __AutoComplete['dropdown'].style.visibility = 'hidden';
    __AutoComplete['highlighted'] = null;
    __AutoComplete['isVisible']   = false;
    __AutoComplete['fromObject'].setAutocompleteIsOpen(false);
    __AutoComplete['element'].onkeydown = __AutoComplete.originalKeyDown;
}

/**
* Highlights a specific item
* 
* @param int    index The index of the element in the dropdown to highlight
*/
function AutoComplete_HighlightItem(index)
{
    if (__AutoComplete['dropdown'].childNodes[index]) {
        for (var i = 0; i < __AutoComplete['dropdown'].childNodes.length; i++) {
            if (__AutoComplete['dropdown'].childNodes[i].className == 'AssetPage_autocomplete_item AssetPage_autocomplete_item_highlighted') {
                __AutoComplete['dropdown'].childNodes[i].className = 'AssetPage_autocomplete_item';
            }
        }
        
        __AutoComplete['dropdown'].childNodes[index].className = 'AssetPage_autocomplete_item AssetPage_autocomplete_item_highlighted';
        __AutoComplete['highlighted'] = index;
    }
}


/**
* Highlights the menu item with the given index
* 
* @param int    index The index of the element in the dropdown to highlight
*/
function AutoComplete_Highlight(index)
{
    // Out of bounds checking
    if (index == 1 && __AutoComplete['highlighted'] == __AutoComplete['dropdown'].childNodes.length - 1) {
        __AutoComplete['dropdown'].childNodes[__AutoComplete['highlighted']].className = 'AssetPage_autocomplete_item';
        __AutoComplete['highlighted'] = null;
    
    } else if (index == -1 && __AutoComplete['highlighted'] == 0) {
        __AutoComplete['dropdown'].childNodes[0].className = 'AssetPage_autocomplete_item';
        __AutoComplete['highlighted'] = __AutoComplete['dropdown'].childNodes.length;
    }

    // Nothing highlighted at the moment
    if (__AutoComplete['highlighted'] == null) {
        __AutoComplete['dropdown'].childNodes[0].className = 'AssetPage_autocomplete_item AssetPage_autocomplete_item_highlighted';
        __AutoComplete['highlighted'] = 0;

    } else {
        if (__AutoComplete['dropdown'].childNodes[__AutoComplete['highlighted']]) {
            __AutoComplete['dropdown'].childNodes[__AutoComplete['highlighted']].className = 'AssetPage_autocomplete_item';
        }

        var newIndex = __AutoComplete['highlighted'] + index;

        if (__AutoComplete['dropdown'].childNodes[newIndex]) {
            __AutoComplete['dropdown'].childNodes[newIndex].className = 'AssetPage_autocomplete_item AssetPage_autocomplete_item_highlighted';
            
            __AutoComplete['highlighted'] = newIndex;
        }
    }
}


/**
* Sets the input to a given value
* 
*/
function AutoComplete_SetValue(){
  var obj = __AutoComplete['dropdown'].childNodes[__AutoComplete['highlighted']];
  var name, id;
  for (var i = 0; i < obj.childNodes.length; i++){
    if (obj.childNodes[i].id.indexOf("autocomplete_item_name_") == 0)
      name = obj.childNodes[i].innerHTML;
    if (obj.childNodes[i].type == 'hidden')
      id = obj.childNodes[i].value;
  }
  __AutoComplete['fromObject'].selectedAutocomplete(id, name);
}


/**
* Checks if the dropdown needs scrolling
* 
*/
function AutoComplete_ScrollCheck()
{
    // Scroll down, or wrapping around from scroll up
    if (__AutoComplete['highlighted'] > __AutoComplete['lastItemShowing']) {
        __AutoComplete['firstItemShowing'] = __AutoComplete['highlighted'] - (__AutoComplete['maxitems'] - 1);
        __AutoComplete['lastItemShowing']  = __AutoComplete['highlighted'];
    }
    
    // Scroll up, or wrapping around from scroll down
    if (__AutoComplete['highlighted'] < __AutoComplete['firstItemShowing']) {
        __AutoComplete['firstItemShowing'] = __AutoComplete['highlighted'];
        __AutoComplete['lastItemShowing']  = __AutoComplete['highlighted'] + (__AutoComplete['maxitems'] - 1);
    }
    
    __AutoComplete['dropdown'].scrollTop = __AutoComplete['firstItemShowing'] * 15;
}


/**
* Function which handles the keypress event
*/
function AutoComplete_KeyDown(event)
{
  var keyCode = event.keyCode;

    switch (keyCode) {

        // Return/Enter
        case 13:
        case 9:
          if (__AutoComplete['highlighted'] == null) {
            markerController.setImageNoteFromInput();
          } else {
            AutoComplete_SetValue();
          }
          AutoComplete_HideDropdown();

          event.returnValue = false;
          event.cancelBubble = true;
          break;

        // Escape
        case 27:
          AutoComplete_HideDropdown();
          event.returnValue = false;
          event.cancelBubble = true;
          break;
        
        // Up arrow
        case 38:
            if (!__AutoComplete['isVisible']) {
                AutoComplete_ShowDropdown();
            }
            
            AutoComplete_Highlight(-1);
            AutoComplete_ScrollCheck(-1);
            return false;
            break;
        
        // Tab
        case 9:
            /*if (__AutoComplete['isVisible']) {
                AutoComplete_HideDropdown();
            }
            return;*/
        
        // Down arrow
        case 40:
            if (!__AutoComplete['isVisible']) {
                AutoComplete_ShowDropdown();
            }
            
            AutoComplete_Highlight(1);
            AutoComplete_ScrollCheck(1);
            return false;
            break;
    }
}


/**
* Function which handles the keyup event
*/
function AutoComplete_KeyUp(event)
{
    var keyCode = event.keyCode;

    switch (keyCode) {
        case 13:
            event.returnValue = false;
            event.cancelBubble = true;
            break;

          case 27:
            AutoComplete_HideDropdown();
            event.returnValue = false;
            event.cancelBubble = true;
            break;
        
        case 38:
        case 40:
            return false;
            break;

        default:
            AutoComplete_ShowDropdown();
            break;
    }
}

// Autocomplete [end]