dojo.provide("parus.catalogTreeModel");
dojo.require("dijit.tree.TreeStoreModel");
dojo.require("parus.parus8");
dojo.require("parus.database");


dojo.declare("parus.treeModel", null, {

  constructor: function(keywordParameters) {
    if (keywordParameters) dojo.mixin(this, keywordParameters);
  },


  isItem: function(something) {
    return true;
  },

  fetchItemByIdentity: function(keywordArgs) {
    parus.parus8.unimplemented(this, "fetchItemByIdentity", arguments);
  },

  newItem: function(args, parent, insertIndex) {
    parus.parus8.unimplemented(this, "newItem", arguments);
  },

  pasteItem: function(childItem, oldParentItem, newParentItem, bCopy) {
    parus.parus8.unimplemented(this, "pasteItem", arguments);
  },

  onChange: function(item) {
    //do nothing due to model is readonly
  },

  onChildrenChange: function(parent, newChildrenList) {
    //do nothing due to model is readonly
  },

  //non-API
  hasAction: function(item, actionCode) {
    return actionCode ? false : true;
  },

  checkAccess: function() {
    return false;
  },

  isValid: function(item) {
    return true;
  },

  refresh: function() {
    //do nothing due to model is empty
  },

  getIdentity: function(item) {
    return null;
  },

  getItem: function(identity) {
    return null;
  }

});


dojo.declare("parus.catalogTreeModel", [parus.treeModel], {

  queryid: null,

  identityFieldName: "ID",

  labelFieldName: "NAME",

  parentLinkFieldName: "PARENT",

  hasChildrenFieldName: "HASCHILDREN",

  onGetConditions: function(model, parentItem) {
    //to override;
  },

  _rootNodes: null,

  _childrenSet: null,

  _hasChildren: null,

  _allFetched: false,

  getConditions: function(parentItem) {
    return this.onGetConditions(this, parentItem)
  },

  getIdentity: function(item) {
    return parus.parus8.nodeField(item, this.identityFieldName) || null;
  },

  getLabel: function(item) {
    return parus.parus8.nodeField(item, this.labelFieldName);
  },

  getParentLink: function(item) {
    return parus.parus8.nodeField(item, this.parentLinkFieldName);
  },

  getValue: function(item, attribute, defaultValue) {
    return parus.parus8.nodeField(item, attribute) || defaultValue || null;
  },

  destroy: function() {
    this._rootNodes = null;
    this._childrenSet = null;
    this._hasChildren = null;
    this._allFetched = false;
  },

  getRoot: function(onItem) {

    if (onItem) {
      if (!this._rootNodes) parus.database.query(this.queryid, this.getConditions(null), dojo.hitch(this, function(response) {
        this._rootNodes = parus.parus8.rowNodes(response);
        dojo.forEach(this._rootNodes, onItem);
      }))
      else dojo.forEach(this._rootNodes, onItem);
    }
  },

  mayHaveChildren: function(item) {
    if (!this._hasChildren) this._hasChildren = [];

    var identity = this.getIdentity(item);
    if (dojo.indexOf(this._hasChildren, identity) >= 0) return true;
    var result = (parus.parus8.nodeField(item, this.hasChildrenFieldName).toString() == "1");
    if (result) this._hasChildren.push(identity);
    return result;
  },

  getChildren: function(parentItem, onComplete) {
    if (onComplete) {
      if (!this.mayHaveChildren(parentItem)) {
        onComplete([]);
        return;
      }
      var children;
      if (this._childrenSet) children = this._childrenSet[this.getIdentity(parentItem)]
      else this._childrenSet = {};

      if (!children) return parus.database.query(this.queryid, this.getConditions(parentItem), dojo.hitch(this, function(response) {
        children = parus.parus8.rowNodes(response);
        this._childrenSet[this.getIdentity(parentItem)] = children;
        onComplete(children);
      }))
      else onComplete(children);
    }
  },

  //non-API functions
  refresh: function() {
    this._rootNodes = null;
    this._childrenSet = null;
    this._hasChildren = null;
    this._allFetched = false;
  },

  newItemCreated: function(item, onCreate) {
    if (!this._hasChildren) this._hasChildren = [];
    if (!this._childrenSet) this._childrenSet = {};
    var identity = this.getIdentity(item);
    this._hasChildren.push(identity);
    this._childrenSet[identity] = null;
    this.getChildren(item, function() {
      if (onCreate) onCreate();
    });
  },

  isValid: function(item) {
    return parus.parus8.nodeField(item, "ISVALID") == "1"
  },

  checkAccess: function() {
    return this._rootNodes ? parus.parus8.nodeField(this._rootNodes[0], "CHECKACCESS") == "1" : false;
  },

  hasAction: function(item, actionCode) {

    if (!actionCode) return true;

    if (!item) return false;

    if (dojo.isIE <= 9) return (item.selectSingleNode("XMLFUNCTIONS/ROWSET/ROW[FUNC='" + actionCode + "']")) ? true : false;

    if (item.children) {
      var nodes = item.children;
      for (var i = 0, ilen = nodes.length; i < ilen; i++) {
        if (nodes[i].nodeName == "XMLFUNCTIONS") if (nodes[i].firstChild) for (var j = 0, jlen = nodes[i].firstChild.children.length; j < jlen; j++) {
          if (nodes[i].firstChild.children[j].nodeName == "ROW") for (var k = 0, klen = nodes[i].firstChild.children[j].children.length; k < klen; k++) {
            if (nodes[i].firstChild.children[j].children[k].firstChild.nodeValue == actionCode) return true;
          }
        }
      }
    }
    else {

      var node = item.firstElementChild;
      while (node) {
        if (node.nodeName == "XMLFUNCTIONS") {
          var nnode = node.firstElementChild ? node.firstElementChild.firstElementChild : null;
          while (nnode) {
            var nnnode = nnode.firstElementChild;
            while (nnnode) {
              if (nnnode.firstChild.nodeValue == actionCode) return true;
              nnnode = nnnode.nextElementSibling;
            }
            nnode = nnode.nextElementSibling;
          }
        }
        node = node.nextElementSibling;
      };
    }

    return false;
  },

  fetchAll: function(loaded) {

    var response = null;
    if (!this._allFetched) {

      var conditions = this.getConditions(null);
      conditions["CRN"] = null;

      response = parus.database.query(this.queryid, conditions);

      var nodes = parus.parus8.rowNodes(response);

      this._childrenSet = {};

      dojo.forEach(nodes, dojo.hitch(this, function(node) {
        var parentIdentity = this.getParentLink(node);
        if (!this._childrenSet[parentIdentity]) this._childrenSet[parentIdentity] = [];
        this._childrenSet[parentIdentity].push(node);
      }));

      this._allFetched = true;
    }

    if (loaded) loaded(this, response);
  },

  getItem: function(identity) {
    var item = null;

    if (this._rootNodes) dojo.forEach(this._rootNodes, dojo.hitch(this, function(node) {
      if (!item && (this.getIdentity(node) == identity)) item = node;
    }));

    if (!item && this._childrenSet) for (var key in this._childrenSet) if (!item) {
      dojo.forEach(this._childrenSet[key], dojo.hitch(this, function(node) {
        if (!item && (this.getIdentity(node) == identity)) item = node;
      }));
    };

    if (!item) {
      var conditions = {};
      conditions[this.identityFieldName] = identity;
      response = parus.database.query(this.queryid, conditions);
      if (response) {
        var nodes = parus.parus8.rowNodes(response);
        if (nodes.length) item = nodes[0];
      }
    };

    return item;
  }

});


dojo.declare("parus.emptyTreeModel", [parus.treeModel], {
  destroy: function() {},

  getRoot: function(onItem) {},

  mayHaveChildren: function(item) {
    return false;
  },

  getChildren: function(parentItem, onComplete) {},

  getIdentity: function(item) {},

  getLabel: function(item) {}

});

dojo.mixin(parus.parus8, {

  emptyTreeModel: function() {
    return new parus.emptyTreeModel();
  }
});