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

/*jslint browser: true, unparam: true, sloppy: true, nomen: true, indent: 2 */

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);
  },
  remove: function (obj) {
    var x, xLen;
    for (x = 0, xLen = this._objList.length; x < xLen; x += 1) {
      if (this._objList[x].id === obj.id) {
        this._objList[x].unsubscribeAll();
        this._objList = this._objList.splice(x, 1);
        break;
      }
    }
  },
  subscribe: function (fn, obj, override) {
    var x, xLen;
    for (x = 0, xLen = this._objList.length; x < xLen; x += 1) {
      if (!this._objList[x][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 || this._objList[x], override || !obj);
    }
  },
  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 || 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, iframes, z, zLen,
        dragEl = this.getDragEl(),
        clickEl = this.getEl();
      if (YAHOO.env.ua.ie) {
        dragEl.innerHTML = clickEl.innerHTML;
        iframes = dragEl.getElementsByTagName("iframe");
        for (z = 0, zLen = iframes.length; z < zLen; z += 1) {
          if (YAHOO.env.ua.ie <= 7) {
            iframes[z].src = "about:blank";
          } else {
            iframes[z].parentNode.removeChild(iframes[z]);
          }
        }
      } else {
        dragEl.innerHTML = "";
        for (x = 0, xLen = clickEl.childNodes.length; x < xLen; x += 1) {
          if (clickEl.childNodes[x].nodeName.toLowerCase() !== "iframe") {
            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");
      if (this.myStartDragEvent) {
        this.myStartDragEvent.fire(clickEl, dragEl, this);
      }
    },
    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());
          if (this.myOnDragDropEvent) {
            this.myOnDragDropEvent.fire(this.getEl(), this);
          }
          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, msg, x, y, p;
      srcEl = this.getEl();
      destEl = YAHOO.util.Dom.get(id);
      if (!destEl) {
        if (!this.dragOverErrorOccurred) {
          msg = ["destEl is undefined.",
                 "Was looking for " + id + ".",
                 "DDM.ids contains:"];
          for (x in this.DDM.ids) {
            if (this.DDM.ids.hasOwnProperty(x)) {
              for (y in this.DDM.ids[x]) {
                if (this.DDM.ids[x].hasOwnProperty(y)) {
                  msg.push("id: " + this.DDM.ids[x][y].id);
                  msg.push("dom id: " + this.DDM.ids[x][y]._domRef.id);
                }
              }
            }
          }
          this.dragOverErrorOccurred = true;
          throw (msg.join(" "));
        } else {
          return;
        }
      }
      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() {
    var x;
    for (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;
    ul = document.getElementById(this._id);
    li = document.getElementById(id);
    if (!li) {
      li = document.createElement(this._tag);
      ul.appendChild(li);
      addAttribute(li, "id", id);
      if (className) {
        li.className = className;
      }
    }
    this._listSortDD = new AZCAT.widgets.listSortDD(id, this._group || this._id, this._config);
    this.endDragEvent.add(this._listSortDD);
    this.onDragDropEvent.add(this._listSortDD);
    this.onDragOverEvent.add(this._listSortDD);
    this.startDragEvent.add(this._listSortDD);
    this._listSortDD._tag = this._tag;
    if (this._config.locked) {
      this._listSortDD.lock();
    }
    this._listSortDDs.push(this._listSortDD);
    return li;
  }
  function removeItem(id) {
    var x, xLen, listSortDD;
    for (x = 0, xLen = this._listSortDDs.length; x < xLen; x += 1) {
      if (this._listSortDDs[x].id === id) {
        listSortDD = this._listSortDDs[x].id;
        this._listSortDDs = this._listSortDDs.splice(x, 1);
        break;
      }
    }
    if (listSortDD) {
      this.endDragEvent.remove(this._listSortDD);
      this.onDragDropEvent.remove(this._listSortDD);
      this.onDragOverEvent.remove(this._listSortDD);
      this.startDragEvent.remove(this._listSortDD);
    }
  }
  function createTargets(targetNames) {
    var x, xLen, dummy;
    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 || {},
      _listSortDDs : [],
      _listSortDD : null,
      addItem : addItem,
      removeItem : removeItem,
      createTargets : createTargets,
      getGoingForward : getGoingForward,
      getLastDraggedOverEl : getLastDraggedOverEl,
      setLastDraggedOverEl : setLastDraggedOverEl,
      resetAllConstraints : resetAllConstraints,
      dragOverErrorOccurred : false,
      endDragEvent : null,
      onDragDropEvent : null,
      onDragOverEvent : null,
      startDragEvent : null
    }, ul, li, x, xLen, haveCreateTargetsConfig, 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.onDragDropEvent = new AZCAT.utils.customEventList("myOnDragDropEvent");
      that.onDragOverEvent = new AZCAT.utils.customEventList("myOnDragOverEvent");
      that.startDragEvent = new AZCAT.utils.customEventList("myStartDragEvent");
      for (x = 0, xLen = li.length; x < xLen; x += 1) {
        haveCreateTargetsConfig = (typeof (that._config.createTargets) !== "undefined");
        if (!haveCreateTargetsConfig || (haveCreateTargetsConfig && that._config.createTargets)) {
          dummy = new YAHOO.util.DDTarget(that._id, that._group);
        }
        that._listSortDD = new AZCAT.widgets.listSortDD(li[x].id, that._group || that._id, that._config);

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

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

