﻿Sitecore.WebEdit.EditFrame = function(rootElement) {
  this.element = $(rootElement);

  this.buttons = this.element.select(".scLooseFrameMenu")[0];
  this.hint = this.element.select(".scFrameHint")[0];
  this.overlay = this.element.select(".scEditFrameOverlay")[0];

  this.debug = (this.element.getAttribute("debug") == "true");

  this.framePadding = parseInt(this.element.getAttribute("framePadding") || "4");
  this.hintOffset = parseInt(this.element.getAttribute("hintOffset") || "8");

  this.state = new Object();
  this.state.menuVisible = false;
  this.state.hintVisible = false;
  this.state.overlayVisible = false;
  this.state.observingMouseMove = false;

  if (this.debug) {
    this.element.setStyle({ border: "solid 1px red" });
  }
};

Sitecore.WebEdit.EditFrame.prototype.checkHideTimer = function(evt) {
  if (!this.state.hintVisible && !this.state.menuVisible) {
    return;
  }

  if (!this.within(Sitecore.WebEdit.lastMouseMove)) {
    this.hideHint("check hide timer - last mouse move outside frame");
    this.hideOverlay("check hide timer - last mouse move outside frame");
    this.hideMenu("check hide timer - last mouse move outside frame");
  }
}

Sitecore.WebEdit.EditFrame.prototype.hideHint = function(reason) {
  console.log("hide hint: %s", reason);

  this.hint.hide();
  this.hint.removeClassName("scFrameHintActive").removeClassName("scFrameHintHover");
  this.stopObservingMouseMove("hide hint (" + reason + ")");
  this.state.hintVisible = false;
}

Sitecore.WebEdit.EditFrame.prototype.hideMenu = function(reason) {
  if (!this.state.menuVisible) {
    return;
  }

  console.log("hide menu: %s", reason);

  this.element.removeClassName("scWebEditHover");

  this.buttons.fade({ duration: 0.1 });
  this.hideOverlay("hide menu");

  this.stopObservingMouseMove("hide menu");
  this.state.menuVisible = false;

  this.hideHint("hide menu");
}

Sitecore.WebEdit.EditFrame.prototype.hideOverlay = function(reason) {
  console.log("hide overlay: %s", reason);

  this.overlay.hide();
  this.state.overlayVisible = false;
}

Sitecore.WebEdit.EditFrame.prototype.hintClick = function() {
  console.group("hint click");

  this.hint.addClassName("scFrameHintActive");
  this.showMenu();

  console.groupEnd("hint click");
}

Sitecore.WebEdit.EditFrame.prototype.getDimensions = function() {
  if (!this._dimensions) {
    this._dimensions = this.layoutRoot().getDimensions();
  }

  return this._dimensions;
}

Sitecore.WebEdit.EditFrame.prototype.item = function() {
  return this.element.getAttribute("sc_item");
}

Sitecore.WebEdit.EditFrame.prototype.layoutRoot = function() {
  return this.element;
}

Sitecore.WebEdit.EditFrame.prototype.load = function() {
  var frame = this;

  this.element.observe("mouseover", function() { this.showHint("element mouseOver"); }.bind(this));

  this.hint.observe("click", this.hintClick.bind(this));

  this.hint.setStyle({ opacity: 0.8 });
  this.hint.observe("mouseover", this.hintMouseOver.bindAsEventListener(this));
  this.hint.observe("mouseout", this.hintMouseOut.bindAsEventListener(this));

  this.overlay.observe("mouseover", function(e) {
    this.hideMenu("overlay mouse over");
    this.showHint();
  } .bind(this));

  this.buttons.select(".scWebEditFrameButtonIcon").each(function(icon) {
    icon.observe("dragstart", function(e) { e.stop(); });
  });

  this.element.select(".scCanHover").each(function(canHover) {
    canHover.observe("mouseover", function() { this.addClassName("scHover"); });
    canHover.observe("mouseout", function() { this.removeClassName("scHover"); });
  });

  this.element.select(".scWebEditFrame").each(function(element) {
    element.observe("mouseover", function(e) {
      frame.showHint();
    });
  });
  
  this.layoutRoot().observe("resize", function() { this._dimensions = null; }.bind(this));
}

Sitecore.WebEdit.EditFrame.prototype.hintMouseOver = function(evt) {
  if (this.state.overlayVisible && Position.within(this.hint, evt.pointerX(), evt.pointerY())) {
    return;
  }
    
  console.group("hint mouse over");

  if (Sitecore.WebEdit.activeElement) {
    Sitecore.WebEdit.activeElement.hide();
  }

  this.hint.addClassName("scFrameHintHover");
  this.hint.setStyle({ opacity: 1 });
  this.showOverlay();

  console.groupEnd("hint mouse over");
}

Sitecore.WebEdit.EditFrame.prototype.hintMouseOut = function(evt) {
  if (Position.within(this.hint, evt.pointerX(), evt.pointerY())) {
    return;
  }
  
  console.log("hint mouseOut");

  this.hint.removeClassName("scFrameHintHover");

  if (!this.state.menuVisible) {
    this.hideOverlay("hint mouseOut");
    this.hint.setStyle({ opacity: 0.8 });
  }  
}

Sitecore.WebEdit.EditFrame.prototype.mouseMove = function(evt) {
  if (this.within(evt)) {
    return;
  }

  this.hideTimer = new Date();
  setTimeout(this.checkHideTimer.bind(this), 250);
}

Sitecore.WebEdit.EditFrame.prototype.nestedFields = function() {
  if (!this._nestedFields) {
    this._nestedFields = this.element.select(".scWebEditInput").map(function(domNode) { return Sitecore.WebEdit.getElement(domNode); }).reject(function(element) { return !element; });
  }

  return this._nestedFields;
}

Sitecore.WebEdit.EditFrame.prototype.observeMouseMove = function(reason) {
  if (this.state.observingMouseMove) {
    console.error("observing mouse move twice: %s", reason);
  }

  console.log("observing mouse move: %s", reason);

  Sitecore.WebEdit.mouseMoveObservers.push(this);
  this.state.observingMouseMove = true;
}

Sitecore.WebEdit.EditFrame.prototype.onNestedFieldShow = function() {
  console.log("showing nested field");

  this.hideMenu("nested field show");
  this.showHint("nested field show");
}

Sitecore.WebEdit.EditFrame.prototype.showHint = function(reason) {
  if (this.state.hintVisible) {
    return;
  }

  if (this.state.menuVisible) {
    return;
  }

  console.log("show hint: %s", reason);

  var dimensions = this.getDimensions();
  var offset = this.layoutRoot().positionedOffset();

  this.hint.setStyle({ top: (offset.top - this.hintOffset - this.hint.getHeight()) + "px", left: (offset.left - this.framePadding) + "px" });
  this.hint.show();
  this.observeMouseMove("show hint");

  this.state.hintVisible = true;
}

Sitecore.WebEdit.EditFrame.prototype.showMenu = function() {
  console.log("show menu");

  this.element.addClassName("scWebEditHover");

  var dimensions = this.getDimensions();
  var offset = this.layoutRoot().positionedOffset();

  this.buttons.setStyle({ left: (offset.left - this.framePadding) + "px", top: (offset.top - 21 - this.framePadding + this.hint.getHeight() -1) + "px" });
  this.buttons.show();

  this.showOverlay();

  this.observeMouseMove("show menu");
  this.state.menuVisible = true;
}

Sitecore.WebEdit.EditFrame.prototype.showOverlay = function() {
  if (this.state.overlayVisible) {
    return;
  }

  console.log("show overlay");

  var dimensions = this.getDimensions();
  var offset = this.layoutRoot().positionedOffset();

  this.overlay.setStyle({ width: (dimensions.width + this.framePadding * 2) + "px", height: (dimensions.height + this.framePadding * 2) + "px", left: (offset.left - this.framePadding) + "px", top: (offset.top - this.framePadding) + "px" });
  this.overlay.select(".scInnerOverlay")[0].setStyle({ opacity: 0.4 });
  this.overlay.show();

  this.state.overlayVisible = true;
}


Sitecore.WebEdit.EditFrame.prototype.setModified = function() {
  this.element.addClassName("scWebEditFrameModified");
}

Sitecore.WebEdit.EditFrame.prototype.stopObservingMouseMove = function(reason) {
  Sitecore.WebEdit.mouseMoveObservers = Sitecore.WebEdit.mouseMoveObservers.without(this);
  
  console.log("stopped observing mouse move: %s", reason);

  this.state.observingMouseMove = false;
}

Sitecore.WebEdit.EditFrame.prototype.within = function(evt) {
  try {
    var withinFrame = Position.within(this.element, evt.pointerX(), evt.pointerY());
    var withinButtons = Position.within(this.buttons, evt.pointerX(), evt.pointerY());
    var withinHint = Position.within(this.hint, evt.pointerX(), evt.pointerY());
  }
  catch(ex) {
    return false;
  }

  return withinFrame || withinButtons || withinHint || this.withinFields(evt);
}

Sitecore.WebEdit.EditFrame.prototype.withinFields = function(evt) {
  var e = evt;
  var fields = this.nestedFields();

  for (var i = 0; i < fields.length; i++) {
    if (fields[i].within(e)) {
      return true;
    }
  }

  return false;
}
