/*global AZCAT,YAHOO,addAttribute,window */

/*jslint white: true, onevar: true, browser: true, on: true, undef: true,
         eqeqeq: true, plusplus: true, bitwise: true, regexp: true,
         newcap: true, immed: true, indent: 2, nomen: false */

AZCAT.utils.customEventList = function (type, oScope, silent, signature) {
  this._type = type;
  this._scope = oScope;
  this._silent = silent;
  this._signature = signature;
  this._objList = [];
};
AZCAT.utils.customEventList.prototype = {
  add: function (obj) {
    this._objList.push(obj);
  },
  subscribe: function (fn, obj, override) {
    var x, xLen;
    for (x = 0, xLen = this._objList.length; x < xLen; x += 1) {
      if (!this._objList[this._type]) {
        this._objList[x][this._type] = new YAHOO.util.CustomEvent(this._type, this._scope, this._silent, this._signature);
      }
      this._objList[x][this._type].subscribe(fn, obj ? obj : this._objList[x], override ? override : obj ? false : true);
    }
  },
  unsubscribe: function (fn, obj) {
    var x, xLen;
    for (x = 0, xLen = this._objList.length; x < xLen; x += 1) {
      this._objList[x].unsubscribe(fn, obj);
    }
  }
};
AZCAT.widgets.listSort = function () {
  // Shared resources, ALL instances
  // Cached singletons

  // Shared helper functions

  // Shared private functions
  AZCAT.widgets.listSortDD = function (id, sGroup, config, vertical) {
    AZCAT.widgets.listSortDD.superclass.constructor.call(this, id, sGroup, config);
    var el = this.getDragEl();
    YAHOO.util.Dom.setStyle(el, "border-color", "transparent");
    YAHOO.util.Dom.setStyle(el, "opacity", 0.67);
    this.forwardOnAxis = false;
    this.lastXY = 0;
    this.lastDraggedOverEl = null;
    this.vertical = vertical ? vertical : true; // Used to determine which way elements move
                                                // so we know to get X or Y data
  };
  YAHOO.extend(AZCAT.widgets.listSortDD, YAHOO.util.DDProxy, {
    startDrag: function (x, y) {
      var styles, xLen,
          dragEl = this.getDragEl(),
          clickEl = this.getEl();
      if (YAHOO.env.ua.ie) {
        dragEl.innerHTML = clickEl.innerHTML;
      } else {
        dragEl.innerHTML = "";
        for (x = 0, xLen = clickEl.childNodes.length; x < xLen; x += 1) {
          dragEl.appendChild(clickEl.childNodes[x].cloneNode(true));
        }
      }
      styles = ["border-left-width", "border-left-color", "border-left-style", "border-right-width", "border-right-color", "border-right-style", "border-top-width", "border-top-color", "border-top-style", "border-bottom-width", "border-bottom-color", "border-bottom-style", "text-align", "color", "background-color", "padding-left", "padding-right", "padding-top", "padding-bottom", "list-sstyle-image", "list-style-position", "list-style-type", "font-family", "font-size", "font-weight", "font-style", "font-variant", "line-height", "cursor", "overflow"];
      for (x = 0, xLen = styles.length; x < xLen; x += 1) {
        YAHOO.util.Dom.setStyle(dragEl, styles[x], YAHOO.util.Dom.getStyle(clickEl, styles[x]));
      }
      if (this.config.constrainX) {
        this.setXConstraint(this.config.constrainX[0], this.config.constrainX[1], this.config.constrainX[2]);
      }
      if (this.config.constrainY) {
        this.setYConstraint(this.config.constrainY[0], this.config.constrainY[1], this.config.constrainY[2]);
      }
      YAHOO.util.Dom.setStyle(clickEl, "visibility", "hidden");
    },
    fixIE6Inputs: function () {
      var x, xLen,
          srcEl = this.getEl(),
          proxy = this.getDragEl(),
          inputs = srcEl.getElementsByTagName("input"),
          proxyInputs = proxy.getElementsByTagName("input");
      for (x = 0, xLen = inputs.length; x < xLen; x += 1) {
        inputs[x].checked = proxyInputs[x].checked;
      }
    },
    clearProxy: function () {
      var proxy = this.getDragEl();
      proxy.innerHTML = "";
    },
    endDrag: function (e) {
      var srcEl = this.getEl(),
          proxy = this.getDragEl(), a, proxyid, thisid;
      YAHOO.util.Dom.setStyle(proxy, "visibility", "");
      a = new YAHOO.util.Motion(proxy, {points: {to: YAHOO.util.Dom.getXY(srcEl)}}, 0.2, YAHOO.util.Easing.easeOut);
      proxyid = proxy.id;
      thisid = this.id;
      a.onComplete.subscribe(function () {
        YAHOO.util.Dom.setStyle(proxyid, "visibility", "hidden");
        YAHOO.util.Dom.setStyle(thisid, "visibility", "");
      });
      if (this.myEndDragEvent) {
        this.myEndDragEvent.fire(srcEl, proxy, this);
      }
      if (YAHOO.env.ua.ie === 6) {
        a.onComplete.subscribe(this.fixIE6Inputs, this, true);
      }
      a.onComplete.subscribe(this.clearProxy, this, true);
      a.animate();
    },
    onDragDrop: function (e, id) {
      var pt, region, destEl, destDD;
      if (YAHOO.util.DDM.interactionInfo.drop.length === 1) {
        pt = YAHOO.util.DDM.interactionInfo.point;
        region = YAHOO.util.DDM.interactionInfo.sourceRegion;
        if (!region.intersect(pt)) {
          destEl = YAHOO.util.Dom.get(id);
          if (destEl.tagName == "LI") {
            return;
          }
          destDD = YAHOO.util.DDM.getDDById(id);
          destEl.appendChild(this.getEl());
          destDD.isEmpty = false;
          YAHOO.util.DDM.refreshCache();
        }
      }
    },
    onDrag: function (e) {
      var xy = this.vertical ? YAHOO.util.Event.getPageY(e) : YAHOO.util.Event.getPageX(e);
      if (xy < this.lastXY) {
        this.forwardOnAxis = true;
      } else if (xy > this.lastXY) {
        this.forwardOnAxis = false;
      }
      this.lastXY = xy;
    },
    onDragOver: function (e, id) {
      var srcEl, destEl, p;
      srcEl = this.getEl();
      destEl = YAHOO.util.Dom.get(id);

      if (destEl.nodeName.toLowerCase() === this._tag) {
        p = destEl.parentNode;
        if (YAHOO.lang.isUndefined(this.config.overriddenMove) || (!YAHOO.lang.isUndefined(this.config.overriddenMove) && !this.config.overriddenMove)) {
          if (this.forwardOnAxis) {
            p.insertBefore(srcEl, destEl); // insert above or left
          } else {
            p.insertBefore(srcEl, destEl.nextSibling); // insert below or right
          }
        }
        if (this.myOnDragOverEvent) {
          this.myOnDragOverEvent.fire(srcEl, destEl, this);
        }
        YAHOO.util.DragDropMgr.refreshCache();
      }
    }
  });
  function getGoingForward() {
    return this._listSortDD.forwardOnAxis;
  }
  function getLastDraggedOverEl() {
    return this._listSortDD.lastDraggedOverEl;
  }
  function setLastDraggedOverEl(el) {
    this._listSortDD.lastDraggedOverEl = el;
  }
  function resetAllConstraints() {
    for (var x in YAHOO.util.DragDropMgr.ids[this._group]) {
      if (YAHOO.util.DragDropMgr.ids[this._group].hasOwnProperty(x)) {
        YAHOO.util.DragDropMgr.ids[this._group][x].resetConstraints();
      }
    }
  }
  function addItem(id, className) {
    var ul, li, x, xLen, dummy;
    ul = document.getElementById(this._id);
    li = document.createElement(this._tag);
    ul.appendChild(li);
    addAttribute(li, "id", id);
    li.className = className;
    this._listSortDD = new AZCAT.widgets.listSortDD(id, this._group ? this._group : this._id, this._config);
    this.endDragEvent.add(this._listSortDD);
    this.onDragOverEvent.add(this._listSortDD);
    this._listSortDD._tag = this._tag;
    if (this._config.locked) {
      this._listSortDD.lock();
    }
    return li;
  }
  function createTargets(targetNames) {
    for (x = 0, xLen = targetNames.length; x < xLen; x += 1) {
      dummy = new YAHOO.util.DDTarget(targetNames[x], this._group);
    }
    dummy = null;
  }

  return function (id, group, tag, config) {
    var that = {
      //Private varables, by convention not actually hidden
      _id : id,
      _group : group || null,
      _tag : tag || "li",
      _config : config || {},
      _listSortDD : null,
      addItem : addItem,
      createTargets : createTargets,
      getGoingForward : getGoingForward,
      getLastDraggedOverEl : getLastDraggedOverEl,
      setLastDraggedOverEl : setLastDraggedOverEl,
      resetAllConstraints : resetAllConstraints,
      endDragEvent : null,
      onDragOverEvent : null
    }, ul, li, x, xLen, dummy;
    if (that._id) {
      YAHOO.util.DragDropMgr.mode = 0;
      ul = document.getElementById(that._id);
      li = ul.getElementsByTagName(that._tag);

      that.endDragEvent = new AZCAT.utils.customEventList("myEndDragEvent");
      that.onDragOverEvent = new AZCAT.utils.customEventList("myOnDragOverEvent");
      for (x = 0, xLen = li.length; x < xLen; x += 1) {
        dummy = new YAHOO.util.DDTarget(that._id, that._group);
        that._listSortDD = new AZCAT.widgets.listSortDD(li[x].id, that._group ? that._group : that._id, that._config);

        that.endDragEvent.add(that._listSortDD);
        that.onDragOverEvent.add(that._listSortDD);
        that._listSortDD._tag = that._tag;
        if (that._config.locked) {
          that._listSortDD.lock();
        }
      }
      dummy = null;

      YAHOO.widget.Module.textResizeEvent.subscribe(that.resetAllConstraints, that, true);
      YAHOO.util.Event.on(window, 'resize', that.resetAllConstraints, that, true);
    }
    return that;
  };
}();
