﻿Sitecore.WebEdit.Element = function(rootElement) {
  this.element = $(rootElement); // span.scWebEditInput
  
  this.frame = $(rootElement.previousSibling); // span.scWebEditFrame
  this.border = $(this.frame.firstChild); // span.scWebEditFrameBorder
  this.buttons = this.frame.select(".scWebEditFrameButtons")[0]; // span.scWebEditButtons  
  this.fieldValue = $(this.frame.previousSibling); // input[type='hidden']
  
  if (this.element.getAttribute("sc_parameters")) {
    this.parameters = this.element.getAttribute("sc_parameters").toQueryParams();
  }
  else {
    this.parameters = new Object();
  }
};

Sitecore.WebEdit.Element.prototype.onBlur = function() {
  if (this.element.innerHTML == "") {
    this.element.innerHTML = this.watermarkHTML;
  }
}

Sitecore.WebEdit.Element.prototype.onClick = function() {
  this.focused = true;

  if (this.isWatermark()) {
    this.element.innerHTML = "";    
  }
}

Sitecore.WebEdit.Element.prototype.equals = function(other) {
  if (!other) {
    return false;
  }

  return this.element == other.element;
}

Sitecore.WebEdit.Element.prototype.load = function() {
  if (this.element.getAttribute("scWatermark") == "true") {
    this.element.removeAttribute("scWatermark");
    this.watermarkHTML = this.element.innerHTML;
  }

  this.buttons.select(".scWebEditFrameButtonIcon").each(function(icon) {
    icon.observe("dragstart", function(e) { e.stop(); });
  });

  this.element.observe("click", this.onClick.bind(this));
  this.element.observe("blur", this.onBlur.bind(this));
}

Sitecore.WebEdit.Element.prototype.hasChildElements = function() {
  return this.element.select(".scWebEditInput").length > 0;
}

Sitecore.WebEdit.Element.prototype.highlight = function() {
  if (this.hasChildElements()) {
    return;
  }

  this.show(true, "highlight");
  
  $(this.border).addClassName("highlight");
  this.buttons.style.visibility = "hidden";
}

Sitecore.WebEdit.Element.prototype.show = function(highlight, reason) {
  console.info("element show: " + reason);

  if (!highlight) {
    var parentFrame = this.parentFrame();

    if (parentFrame) {
      parentFrame.onNestedFieldShow();
    }
  }

  var frame = this.frame;
  var element = this.element;

  frame.attributeHistory = { onresize: element.onresize, position: element.style.position };

  var dimensions = this.layoutRoot().getDimensions();
  var width = dimensions.width;
  var height = dimensions.height;

  if (width == 0 && Prototype.Browser.IE) {
    element.contentEditable = true;
    width = element.offsetWidth;
    element.contentEditable = false;
  }

  // in firefox, inline webeditinput spans that have block content are reported to have 0 size.
  if (width == 0 && Prototype.Browser.Gecko && element.getStyle("display") == "inline") {
    element.setStyle({ display: "block" });
    width = element.getWidth();
    height = element.getHeight();
    element.setStyle({ display: "inline" });
  }

  var border = this.border;

  var spacing = 8;
  border.setStyle({ width: width + spacing + "px", height: height + spacing + "px" });

  var className = this.focused ? "scWebEditFrameBorderFocused" : "scWebEditFrameBorder";
  $(border).addClassName(className);

  element.onresize = function() { return Sitecore.WebEdit.resize(this) };

  frame.show();

  if (Sitecore.WebEdit.quirksMode()) {
    this.updateButtonsWidth();
  }

  if (!highlight && this.parentElement()) {
    this.moveButtonsFromParent();
  }

  var offset = this.offset(this.layoutRoot());
  frame.setStyle({ left: offset.left, top: offset.top });


  /* if the element is content editable, we need to position it on top of the frame so it can receive clicks. hence the relative positioning. */
  if (this.contentEditable()) {
    element.setStyle({ position: "relative" });
  }

  var parentLink = element.up("a")
  if (parentLink) {
    this.originalTextDecoration = parentLink.style.textDecoration;
    parentLink.style.textDecoration = 'none';
  }
}

Sitecore.WebEdit.Element.prototype.hide = function(highlight, reason) {
  console.info("element hide: " + reason);

  var parentLink = this.element.up("a")
  if (parentLink) {
    parentLink.style.textDecoration = this.originalTextDecoration;
  }

  this.frame.hide();
  $(this.border).removeClassName("scWebEditFrameBorderFocused").addClassName("scWebEditFrameBorder");

  if (!highlight && this.parentElement()) {
    this.returnButtonsToParent();
  }

  this.buttons.style.visibility = 'visible';
  this.focused = false;

  var attributeHistory = this.frame.attributeHistory;
  if (!attributeHistory) {
    return;
  }

  if (attributeHistory.onresize) {
    this.element.onresize = attributeHistory.onresize;
  }

  this.element.style.position = attributeHistory.position;
}

Sitecore.WebEdit.Element.prototype.updateButtonsWidth = function() {
  var width = 8;

  this.buttons.select(".scWebEditFrameButton").each(function(button) {
    width += button.getWidth();
  });

  this.buttons.setStyle({ width: width });
}

Sitecore.WebEdit.Element.prototype.contentEditable = function() {
  return this.element.contentEditable == 'true';
}

Sitecore.WebEdit.Element.prototype.fieldType = function() {
  return this.element.getAttribute("scFieldType");
}

Sitecore.WebEdit.Element.prototype.isWatermark = function() {
  return this.watermarkHTML == this.element.innerHTML;
}

/* gets the element that will be used to position the webedit frame and determine it's size. when wrapped content has a single root node, we use it instead of Sitecore's wrapper to reduce the amount of positioning bugs */
Sitecore.WebEdit.Element.prototype.layoutRoot = function() {
  if (this.element.childNodes.length == 1 && this.element.childNodes[0].nodeName != "#text") {
    return $(this.element.childNodes[0]);
  }
  else {
    return this.element;
  }
}

Sitecore.WebEdit.Element.prototype.offset = function(element) {
  return $(element).positionedOffset();
}

Sitecore.WebEdit.Element.prototype.parentElement = function() {
  if (this._parentElement) {
    return this._parentElement;
  }

  this._parentElement = this.element.up(".scWebEditInput");
  if (this._parentElement != null) {
    this._parentElement = Sitecore.WebEdit.getElement(this._parentElement);
    return this._parentElement;
  }
  
  return null;
}

Sitecore.WebEdit.Element.prototype.parentFrame = function() {
  var element = this.element.up(".scLooseFrameZone");
  if (!element) {
    return element;
  }

  var frame = Sitecore.WebEdit.frames().find(function(frame) {
    return frame.element == element;
  });

  return frame;
}

/* persists content editable value in a hidden input, so it can be received by the server as a form value */
Sitecore.WebEdit.Element.prototype.persistValue = function() {
  if (this.isWatermark()) {
    return;
  }
  
  if (this.fieldValue.value != this.element.innerHTML) {
    this.setModified();
  }
  this.fieldValue.value = this.element.innerHTML;
}

Sitecore.WebEdit.Element.prototype.returnButtonsToParent = function() {
  var parent = this.parentElement();
  
  for (var i = 0; i < this.buttons.childNodes.length; i++) {
    var button = this.buttons.childNodes[i];
    
    if (button.originalElement == parent.element) {
      parent.buttons.appendChild(button);
    }
  }
}

Sitecore.WebEdit.Element.prototype.moveButtonsFromParent = function(){
  var parent = this.parentElement();
  
  for (var i = 0; i < parent.buttons.childNodes.length; i++) {
    var button = parent.buttons.childNodes[i];
    
    if (button.getAttribute("type") == "common") {
      continue;
    }
    
    button.originalElement = parent.element;
    button.style.marginRight = "4px";
    this.buttons.insertBefore(button, this.buttons.firstChild);
  }
}

Sitecore.WebEdit.Element.prototype.refreshValue = function() {
  if (!this.contentEditable()) {
    return;
  }

  if (this.fieldValue.value != this.element.innerHTML) {
    this.element.innerHTML = this.fieldValue.value;
  }
}

Sitecore.WebEdit.Element.prototype.resize = function() {
  var dimensions = this.layoutRoot().getDimensions();
  var spacing = 8;

  this.border.setStyle({ width: dimensions.width + spacing + "px", height: dimensions.height + spacing + "px" });
  return false;
}

Sitecore.WebEdit.Element.prototype.setModified = function() {
  //$(this.element).addClassName("scWebEditModified");
}

Sitecore.WebEdit.Element.prototype.within = function(evt) {
  var withinBorder = Position.within(this.border, evt.pointerX(), evt.pointerY());
  var withinButtons = Position.within(this.buttons, evt.pointerX(), evt.pointerY());

  return withinBorder || withinButtons;
}
