var MarkerEditor = Class.create();
MarkerEditor.prototype = {
	initialize: function(map, p_markerListDiv, p_onUnsavedChanges, p_geoCoderControl) {
		this.defaultMarkerTitle = 'Markør';
		this.allowCreateMarkers = true
		this.onUnsavedChanges = p_onUnsavedChanges;
		this.g_map = map;
		this.markerListDiv = $(p_markerListDiv);
    this.markerId = 0;
    this.markers = new Object;
    this.currentMarkerForm = null;
    this.hitMarker = null;
  	this.hitData = null;
  	this.deletedMarkers = [];
  	this.unsavedChanges = false;
    this.preloadingData = 0;
		if(p_geoCoderControl) {
			this.geoCoderControl = p_geoCoderControl;
		} else {
			this.geoCoderControl  = new LGeoCoderControl();
		}
		
    this.geoCoderControl.onInitiate = function() { this.resetHit(); }.bind(this);
    this.geoCoderControl.onHit = function(point, data) { this.setHit(point, data); }.bind(this);
		this.g_map.addControl(this.geoCoderControl);

  	/* An icon for the hit */
  	this.hitIcon = new GIcon();
  	this.hitIcon.image = 'http://localhost:3000/images/hotspot.png';
  	this.hitIcon.shadow = null;
  	this.hitIcon.iconAnchor = new GPoint(12,12);
  	this.hitIcon.iconSize = new GSize(24,24);
  	this.hitIcon.infoWindowAnchor = new GPoint(12,12);		
	},
	
	beginPreloading: function() { this.preloadingData += 1 },
	donePreloading: function() { this.preloadingData -= 1; },
	isPreloading: function() { return(this.preloadingData > 0); },
	
  hasUnsavedChanges: function() {
    if(!this.unsavedChanges && !this.isPreloading()) {
      this.unsavedChanges = true;
      this.onUnsavedChanges();
    }
  },

  resetHit: function() {
    if (this.hitMarker) { g_map.removeOverlay(this.hitMarker); }
		this.hitMarker = null;  		
		this.hitData = null;
	  this.g_map.closeInfoWindow();
  },

	setHit: function(point, data) {
		this.g_map.panTo(point);
		this.hitMarker = new GMarker(point, this.hitIcon);
    GEvent.addListener(this.hitMarker, "click", function() { 
			this.focusHit();
		}.bind(this));
		this.g_map.addOverlay(this.hitMarker);
		this.hitData = data;
		this.focusHit();
  },

  placeMarkerOnHit: function() {
    point = this.hitMarker.getPoint();
    //var newMarkerId = this.addMarker(true, this.hitData.text, '', point.x, point.y, null);
    var newMarkerId = this.addMarker({
      editable:true, 
      title: this.hitData.text, 
      body: '', 
      x: point.x, 
      y: point.y, 
      databaseId: null
    });
    this.resetHit();
    this.infoWindowForMarker(newMarkerId);
  },

  focusHit: function() {
    var geocodingHitDescriptionDiv = document.createElement("div");
    geocodingHitDescriptionDiv.className = "geocoding_hit_bubble"
    
    var resultStringDiv = document.createElement("div");
    resultStringDiv.className = "result_string"
    resultStringDiv.appendChild(document.createTextNode(this.hitData['text']));
    geocodingHitDescriptionDiv.appendChild(resultStringDiv);

    if(this.allowCreateMarkers) {
		  var createMarkerLinkElement = document.createElement("a");
		  createMarkerLinkElement.href = "#";		  
		  createMarkerLinkElement.className = 'place_marker_link'
		  createMarkerLinkElement.onclick = function() { this.placeMarkerOnHit(); }.bind(this);
		  createMarkerLinkElement.appendChild(document.createTextNode("Plasser markør her"));
		  createMarkerLinkElement.appendChild(document.createElement('span'));
	    geocodingHitDescriptionDiv.appendChild(createMarkerLinkElement);
		}
    
    this.hitMarker.openInfoWindow(geocodingHitDescriptionDiv);
  },
  
  _icon: function(name) {
    var icon = new GIcon();
    icon.iconSize = new GSize(21,31);;
    icon.iconAnchor = new GPoint(10, 31);
    icon.shadowSize = new GSize(21, 31);
    icon.infoWindowAnchor = new GPoint(11, 5);
		icon.image = "/images/markers/" + name + ".png";
		icon.shadow = "/images/markers/color_marker_shadow.png";
		return icon;
  },
  
  addMarker: function(parameters) {
		this.parameters = parameters || {};
		this.parameters.rawTitle = this.parameters.rawTitle || this.parameters.title;
		this.parameters.rawBody = this.parameters.rawBody || this.parameters.body;
    this.g_map.closeInfoWindow();
	  this.markerId += 1;
	  var thisMarker = this.markerId;
	  if(typeof this.parameters.x == "undefined") {
	    point = this.g_map.getCenter();
	  } else {
	    point = new GPoint(this.parameters.x,this.parameters.y);
	  }
	  var g_icon = this.parameters.canonical ? this._icon("yellow") : this._icon("orange");
    g_marker = new GMarker(point, {icon: g_icon, draggable: this.parameters.editable});
	  this.g_map.addOverlay(g_marker);
	  if(typeof this.parameters.body == "undefined") { this.parameters.body=''; };
	  if(typeof this.parameters.databaseId == "undefined") { this.parameters.databaseId = null; };

	  this.markers[this.markerId] = {
	    overlay: g_marker, 
	    body: this.parameters.body, 
	    databaseId: this.parameters.databaseId, 
	    editable: this.parameters.editable,
	    title: this.parameters.title,
	    rawTitle: this.parameters.rawTitle,
	    rawBody: this.parameters.rawBody,
			authorName: this.parameters.authorName,
			authorId: this.parameters.authorId
		};
	  var markerDiv = document.createElement("div");
	  markerDiv.id = "marker_"+this.markerId;
	  markerDiv.className = "marker_entry";
	  this.markerListDiv.appendChild(markerDiv);
	  
	  var focusLinkElement = document.createElement("a");
	  focusLinkElement.className = 'marker_focus_link'
	  focusLinkElement.href="#";
	  focusLinkElement.onclick = function() { this.infoWindowForMarker(thisMarker); }.bind(this);
		focusLinkElementIcon = document.createElement('img');
		if (this.parameters.canonical) {
		  focusLinkElementIcon.src = "/images/markers/dot_yellow_24.png";
		} else {
		  focusLinkElementIcon.src = "/images/markers/dot_orange_24.png";		  
		}
	  focusLinkElement.appendChild(focusLinkElementIcon);
	  markerDiv.appendChild(focusLinkElement);
	  
	  if(this.parameters.editable) {
	    /* Form elements for editable markers */
		  var titleInputElement = document.createElement("input");
		  titleInputElement.id = 'marker_'+this.markerId+'_title';
		  titleInputElement.name = 'markers['+this.markerId+'][title]';
		  titleInputElement.type = 'text';
		  titleInputElement.size = '27';
			titleInputElement.onfocus = function(event) {
				if(titleInputElement.value == this.defaultMarkerTitle) {
					titleInputElement.value = '';
				}
			}.bind(this);
			titleInputElement.onblur = function(event) {
				if(titleInputElement.value == '') {
					titleInputElement.value = this.defaultMarkerTitle;
				}
			}.bind(this);
			Event.observe(titleInputElement, "keypress", function(event) {
        if (Event.getKey(event) == Event.KEY_RETURN) {
		      this.blur();
					return false;
		    }
		    this.hasUnsavedChanges();
		  }.bind(this));
		
		  if(typeof this.parameters.title == "undefined") {
		    titleInputElement.value = this.defaultMarkerTitle;
	    } else {
	      titleInputElement.value = this.parameters.rawTitle;
	    }

		  markerDiv.appendChild(titleInputElement)
	  
		  var deleteLinkElement = document.createElement("a");
		  deleteLinkElement.className = "delete_marker_link";
		  deleteLinkElement.href = "#";
		  deleteLinkElement.onclick = function() { this.removeMarker(thisMarker); }.bind(this);
      markerDiv.insertBefore(deleteLinkElement,focusLinkElement)
  	  var clearDiv = document.createElement("div");
  	  clearDiv.className = "clear";
      this.markerListDiv.appendChild(clearDiv);


	  } else {
	    var titleElement = document.createElement("a");
	    titleElement.className = "marker_title";
	    titleElement.href = "#";
	    titleElement.onclick = function() { this.infoWindowForMarker(thisMarker); }.bind(this);
	    titleElement.innerHTML = this.parameters.title;
	    markerDiv.appendChild(titleElement);
	  }
	
    GEvent.addListener(g_marker, "click", function() { 
			this.infoWindowForMarker(thisMarker); 
		}.bind(this));
    GEvent.addListener(g_marker, "drag", function() { 
			this.hasUnsavedChanges(); 
			this.g_map.closeInfoWindow(); 
		}.bind(this));
    /* this.hasUnsavedChanges(); */
		if (!this.isPreloading()) {
			setTimeout(function() { this.markerListDiv.scrollTop = 65534; }.bind(this), 200);
			markerDiv.style.display = 'none';
			new Effect.Appear(markerDiv, {duration: 1});
			this.infoWindowForMarker(this.markerId);
		}
    return(this.markerId);
	},
	
	removeMarker: function(id) {
	  this.hasUnsavedChanges();
    this.g_map.closeInfoWindow();
	  this.g_map.removeOverlay(this.markers[id].overlay);
	  this.markerListDiv.removeChild($("marker_"+id));
	  /* Keep a list of markers we will delete when this is posted */
	  if(this.markers[id].databaseId) {
	    this.deletedMarkers.push(this.markers[id].databaseId);
	  }
	  delete this.markers[id];
	},
	
	focusMarker: function(id) {
	  this.g_map.panTo(this.markers[id].overlay.getPoint());
	},
	
	infoWindowForMarker: function(id) {
	  var thisMarker = id

    if(this.markers[id].editable) {
      /* Marker edit form */
		  this.currentMarkerForm = document.createElement("form");
		  this.currentMarkerForm.className = 'marker_form'
      // this.currentMarkerForm.style.width = "300px;"

      var label = document.createElement('label');
      label.appendChild(document.createTextNode('Tittel'));
      this.currentMarkerForm.appendChild(label)

		  var titleInputElement = document.createElement("input");
		  titleInputElement.id = 'marker_title';
		  titleInputElement.type = 'text';
		  titleInputElement.size = '28';
		  titleInputElement.value = $('marker_'+id+'_title').value
		  this.currentMarkerForm.appendChild(titleInputElement);

		  this.currentMarkerForm.appendChild(document.createElement('br'));
    
      label = document.createElement('label');
      label.appendChild(document.createTextNode('Beskrivelse'));
      this.currentMarkerForm.appendChild(label)

		  var input = document.createElement('textarea');
		  input.id = "marker_body";
		  input.cols = 28;
		  input.style.fontSize = '9pt';
		  input.rows = 7;
		  input.value = this.markers[id].rawBody
		  this.currentMarkerForm.appendChild(input);

		  input = document.createElement('input');
		  input.type = 'hidden';
		  input.id = 'marker_id';
		  input.value = id
		  this.currentMarkerForm.appendChild(input);

		  this.currentMarkerForm.appendChild(document.createElement('br'));

  	  input = document.createElement('input');
  	  input.type = 'submit';
  	  input.value = 'Ok';
      input.className = 'submit_marker';
  	  input.onclick = function() { 
  	    this.processMarkerForm();
        this.hasUnsavedChanges();
  	    return(false); 
	    }.bind(this);
		  this.currentMarkerForm.appendChild(input);

		  var deleteLinkElement = document.createElement("a");
		  deleteLinkElement.href = "#";		  
		  deleteLinkElement.className = 'delete_marker_link';
		  deleteLinkElement.onclick = function() { this.removeMarker(thisMarker); }.bind(this);
		  deleteLinkElement.appendChild(document.createTextNode("Fjern markør"));
		  deleteLinkElement.appendChild(document.createElement('span'));
		  this.currentMarkerForm.appendChild(deleteLinkElement);      

	    this.markers[id].overlay.openInfoWindow(this.currentMarkerForm);
	  } else {
	    /* Show marker content */
		  metadataDiv = document.createElement("div");
		  metadataDiv.className = 'marker_metadata_bubble';
		  
		  titleElement = document.createElement("h3");
		  titleElement.innerHTML = this.markers[id].title;
		  metadataDiv.appendChild(titleElement);
		  
		  descriptionElement = document.createElement("div");
		  descriptionElement.className = "marker_body"
		  descriptionElement.innerHTML = this.markers[id].body;
		  metadataDiv.appendChild(descriptionElement);

			if(this.markers[id].authorId) {
			  bylineElement = document.createElement("div");
				bylineElement.className = "metadata";
				bylineElement.innerHTML = "Markert av <a href='/user/show/"+
				  this.markers[id].authorId+"'>"+this.markers[id].authorName+"</a>";
			  metadataDiv.appendChild(bylineElement);
			}
			
	    this.markers[id].overlay.openInfoWindow(metadataDiv, { maxWidth: 200 } );
	  }
	},
	
	processMarkerForm: function() {
	  var formData = new Object
	  nodes = this.currentMarkerForm.childNodes
    for (var i=0;i<nodes.length;i++) {
	    node = nodes[i]
	    if(node.value) {
	      formData[node.id] = node.value;
	    }
	  }
	  this.currentMarkerForm = null;
    
    thisMarker = this.markers[formData['marker_id']];
    thisMarker.body = formData['marker_body'];
    $('marker_'+formData['marker_id']+'_title').value = formData['marker_title'];
    this.g_map.closeInfoWindow();
	},
	
	prepareToSubmitMarkers: function() {
	  markerFields = this.markerListDiv;
	  for(marker in this.markers) {
	    markerObject = this.markers[marker]
	    if (markerObject.editable) {
	    
		    if(markerObject.body) {
    		  input = document.createElement('input');
    		  input.type = 'hidden';
    		  input.name = 'markers['+marker+'][body]';
    		  input.value = markerObject.body
    		  markerFields.appendChild(input);
  		  }
		  
		    if(markerObject.databaseId) {
    		  input = document.createElement('input');
    		  input.type = 'hidden';
    		  input.name = 'markers['+marker+'][id]';
    		  input.value = markerObject.databaseId;
    		  markerFields.appendChild(input);
  		  }
		  
  		  input = document.createElement('input');
  		  input.type = 'hidden';
  		  input.name = 'markers['+marker+'][x]';
  		  input.value = markerObject.overlay.getPoint().x
  		  markerFields.appendChild(input);

  		  input = document.createElement('input');
  		  input.type = 'hidden';
  		  input.name = 'markers['+marker+'][y]';
  		  input.value = markerObject.overlay.getPoint().y
  		  markerFields.appendChild(input);
		  }
	  }
	  
	  input = document.createElement('input');
	  input.type = 'hidden';
	  input.name = 'deleted_markers';
	  input.value = this.deletedMarkers.join(',');
	  markerFields.appendChild(input);
	},
	
	resetView: function() {
	  bounds = null
	  for(marker in this.markers) {
	    g_marker = this.markers[marker].overlay
			if (!bounds) {
			  bounds = new GLatLngBounds(g_marker.getPoint(), g_marker.getPoint());
			} else {
			  bounds.extend(g_marker.getPoint());
			}
		}
		if (bounds) {
  		this.g_map.setZoom(this.g_map.getBoundsZoomLevel(bounds));
      this.g_map.setCenter(bounds.getCenter());
    }
	}
}