dojo.provide("parus.templateGridPaneMixins");

dojo.require("parus.templateGridPane");
dojo.require("parus.excelFormulas");
dojo.require("parus.designerEdit");
dojo.require("parus.balanceUnitsDialog");

dojo.declare("parus.templateGridPaneInplaceEditor", dojo.Stateful, {

  id: null,

  pane: null,

  balanceIndex: null,

  value: null,

  dataType: null,

  strLen: null,

  intPart: null,

  fracPart: null,

  regExp: null,

  nullable: null,

  dictCheck: null,

  dictNote: null,

  dicts: null,

  col: null,

  row: null,

  dictionary: null,

  connection: null,

  valueNode: null,

  editWidget: null,

  node: null,

  modified: false,

  canEdit: true,

  valueChanged: null,

  _onPasteConnection: null,

  cancelValue: function() {

    if (!this.editWidget) return;

    dijit.hideTooltip(this.editWidget.domNode);

    if (this._onPasteConnection) dojo.disconnect(this._onPasteConnection);

    setTimeout(dojo.hitch(this.editWidget, this.editWidget.destroyRecursive), 100);

    this.editWidget = null;
    this.connection = dojo.connect(this.node, "onclick", dojo.hitch(this, this.clickHandler));
    this.pane.editing = null;

    this.pane.selectCell(this.node);
    this.pane.focusTemplate();

  },

  postValue: function() {
    if (!this.editWidget) return true;

    dijit.hideTooltip(this.editWidget.domNode);

    if (this.editWidget.validate) {
      if (!this.editWidget.validate()) {
        dijit.focus(this.editWidget.focusNode || this.editWidget.domNode);
        return false;
      }
    };

    var vc = this.pane.setCellText(this.node, this.valueNode, this.editWidget.value);

    this.modified = true;

    if (this._onPasteConnection) dojo.disconnect(this._onPasteConnection);

    setTimeout(dojo.hitch(this.editWidget, this.editWidget.destroyRecursive), 100);

    this.editWidget = null;
    this.connection = dojo.connect(this.node, "onclick", dojo.hitch(this, this.clickHandler));
    this.pane.editing = null;
    this.pane.modified = true;
    this.pane.onModified();

    if (vc) if (this.valueChanged) this.valueChanged(this.id);

    this.pane.selectCell(this.node);
    this.pane.focusTemplate();

    return true;

  },

  clickHandler: function(e) {

    var evt = e || event;

    parus.parus8.registerAction();

    this.pane.selectCell(this.node, ( !! evt.shiftKey) || ( !! evt.altKey) || ( !! evt.ctrlKey));

    if (( !! evt.shiftKey) || ( !! evt.altKey) || ( !! evt.ctrlKey)) return;

    if (this.pane.editing) if (!this.pane.editing.postValue()) return;

    if (!this.valueNode) return;

    dojo.disconnect(this.connection);

    var constructor = function() {
      return null;
    };

    var cls = this.node.className.split(" ");
    cls.unshift("templateGridInplaceEdit");

    dojo.query("[class]", this.node).forEach(function(node) {
      cls = cls.concat(node.className.split(" "));
    });

    cls = dojo.filter(cls, function(cls) {
      return (cls != "templateGridActiveCellBorder") && (cls != "templateGridActiveCellBk");
    });

    var creationParams = {
      intermediateChanges: true,

      selectOnClick: true,

      value: parus.parus8.externalStringToValue(
      parus.parus8.getTextContent(this.valueNode), this.dataType),

      onBlur: dojo.hitch(this, function() {
        if (!this.editWidget) return;
        if (this.editWidget.showingDictionary) return;
        if (this.editWidget.showingDialog) return;

        this.postValue();
      }),

      "class": cls.join(" "),

      required: !this.nullable,

      onKeyDown: dojo.hitch(this, function(event) {
        if ((event.keyCode == 13) || (event.keyCode == 9)) {
          var direction = (event.keyCode == 13) ? this.pane.moveAfterReturnDirection : (event.shiftKey ? 37 : 39);
          if (this.postValue()) this.pane.keyDown({
            keyCode: direction,
            shiftKey: false,
            cancelBubble: false
          });
          if (event.preventDefault) event.preventDefault();
          if (event.stopPropagation) event.stopPropagation();
          event.cancelBubble = true;
          event.keyCode = 0;
          return false;

        }
        else if (event.keyCode == 27) this.cancelValue()
      })
    };

    if (this.dicts) {

      constructor = function() {
        return parus.templateGridDesignerEdit
      };

      dojo.mixin(creationParams, {
        dicts: this.dicts,

        subreport: this.pane.subreport,

        onApplyDictionary: dojo.hitch(this, function(dialog) {
          this.postValue();
        })

      });

    }
    else if (this.dictionary) {
      constructor = function() {
        return parus.extraDictEdit
      };

      var searchAttr = this.dictNote ? "NOTE" : "VALUE";

      dojo.mixin(creationParams, {
        extraDictionaryCode: this.dictionary,
        agent: this.pane.agent,
        section: this.pane.section,
        arbitrary: !this.dictCheck,
        searchAttr: searchAttr
      });

      if (this.node.getAttribute("tid")) {

        dojo.mixin(creationParams, {
          dialogClass: parus.balanceTemplateGridExtraDictionaryDialog,
          multiselect: true,
          onApplyDictionary: dojo.hitch(this, function(dialog) {

            if (dialog.cloneTable.checked) {

              var item = dialog.grid.selection.getFirstSelected();
              this.editWidget.setValue(dialog.grid.store.getValue(item, searchAttr));

              item = dialog.grid.selection.getNextSelected(item);

              var table = this.pane._tables.byKey[this.node.getAttribute("tid")];

              while (item) {
                var clone = table.placeClone();
                dojo.forEach(clone._staticValues, dojo.hitch(this, function(staticValue) {
                  if (staticValue.id == this.id) this.pane.setCellText(staticValue.node, staticValue.valueNode, dialog.grid.store.getValue(item, searchAttr));
                }));
                item = dialog.grid.selection.getNextSelected(item);
              };
              this.postValue();
            }
            else {
              var item = dialog.grid.selection.getFirstSelected();
              if (item) this.editWidget.setValue(dialog.grid.store.getValue(item, searchAttr));
              this.postValue();
            }

          })
        });

      }
    }

    else if (this.dataType == "1") {
      constructor = function() {
        return parus.templateGridPaneNumberEdit
      };

      var pattern = "";
      for (var i = 0; i < this.intPart; i++)
      pattern = pattern + "#";
      if (this.fracPart) {
        pattern = pattern + ".";
        for (var i = 0; i < this.fracPart; i++)
        pattern = pattern + "#";
      };

      dojo.mixin(creationParams, {
        constraints: {
          min: this.minVal ? dojo.number.parse(this.minVal.toString().split(".").join(",")) : -9999999999999999,
          max: this.maxVal ? dojo.number.parse(this.maxVal.toString().split(".").join(",")) : 9999999999999999,
          pattern: pattern
        },
        editOptions: {
          pattern: pattern
        },
        onKeyPress: dojo.hitch(this, function(evt) {
          if (evt.charCode == 46) {
            var s = evt.target.value;

            var range = dijit.getSelectionRange(evt.target);

            var selStart = range.start;
            var selEnd = range.end;
            s = s.substring(0, selStart) + "," + s.substring(selEnd, s.length);

            if (this.editWidget) this.editWidget.attr("value", s);

            setTimeout(dojo.hitch(this, function() {
              dijit.selectInputText(evt.target, selStart + 1, selEnd + 1);
            }), 0);

            if (evt.preventDefault) evt.preventDefault();
            if (evt.stopPropagation) evt.stopPropagation();
            evt.cancelBubble = true;
            return false;
          }
        })
      });

    } else if (this.dataType == "2") {

      constructor = function() {
        return dijit.form.DateTextBox
      };

    }
    else if (this.node.getAttribute("wt")) {
      constructor = function() {
        return dijit.form.SimpleTextarea
      };

      dojo.mixin(creationParams, {
        rows: "",
        cols: ""
      });

    }
    else {
      constructor = function() {
        return dijit.form.ValidationTextBox
      };

      dojo.mixin(creationParams, {
        maxLength: this.strLen || 255,
        trim: this.trim == "1",
        regExp: this.regExp || ".*"
      });
    };

    this.editWidget = new(constructor())(creationParams, this.node.appendChild(document.createElement("div")));

    this.pane.editing = this;

    if (this.editWidget) {

      if (this.editWidget.declaredClass == "dijit.form.SimpleTextarea") this.editWidget.domNode.removeAttribute("cols");
      else this._onPasteConnection = dojo.connect(this.editWidget.focusNode, "onpaste", this, "_onPaste");

      var focusNode = this.editWidget.focusNode;
      if (focusNode && focusNode.focus) {
        try {
          if (dojo.isFF) {
            var x = this.pane.containerNode.scrollTop;
            focusNode.focus({
              preventScroll: true
            });
            this.pane.containerNode.scrollTop = x;
          }
          else focusNode.focus({
            preventScroll: true
          });
        } catch (e) {};
      }

      if (this.editWidget) if (this.editWidget.textbox) dijit.selectInputText(this.editWidget.textbox);
    }
  },

  _onPaste: function(e) {
    var evt = e || event;

    if (!evt) return;

    var clp = evt.clipboardData || clipboardData;

    if (!clp) return;

    var text =
    dojo.filter(dojo.map(clp.getData("text").split("\n") || [], function(line) {
      return line ? line.split(String.fromCharCode(9)) : []
    }), function(line) {
      return !!line.length
    });

    if (text.length == 0) return;

    if (text.length == 1 && text[0].length < 2) return;

    this.cancelValue();

    dojo.stopEvent(evt);

    var pane = this.pane;

    pane._doPasteTexts(this.node, text);

    pane.selectCell(this.node);
    pane.focusTemplate();
  }

});

dojo.declare("parus.templateGridPaneFormulasMixin", [parus.excelFormulas], {

  __currentFormatCondition: function(Row, Col) {
    return {
      value: this.__fromReference(Row, Col, null),
      node: this.getCell("R" + Row + "C" + Col)
    };
  },

  __applyFormatCondition: function(node, className) {

    var apply = function(node) {

      var oldClasses = node.className.split(" ") || [""];
      var newClasses = [oldClasses[0]];

      for (var i = 0; i < oldClasses.length; i++)
      if ((oldClasses[i] == "templateGridActiveCellBorder") || (oldClasses[i] == "uninitializedTable") || (oldClasses[i] == "templateGridActiveCellBk")) newClasses.push(oldClasses[i]);

      if (className) newClasses.push(className);

      node.className = newClasses.join(" ");
    };

    apply(node);
    dojo.query("[class]", node).forEach(apply);

  },

  tossDependencies: function(dependencies, deps) {

    var swap;
    var count = 0;

    do {
      swap = false;
      count++;


      for (var formula in dependencies) {
        var f = dojo.indexOf(deps, formula);
        if (f !== -1) {
          dojo.forEach(dependencies[formula], function(dep) {
            var g = dojo.indexOf(deps, dep);
            if ((g !== -1) && (g < f)) {
              var q = deps[f];
              deps[f] = deps[g];
              deps[g] = q;
              swap = true;
            }
          });
        }
      };
    } while (swap && (count < 10));


    if (count >= 10) console.log("Formula tosser error.", {
      dependencies: deps,
      dependenciesList: dependencies
    });

    dojo.forEach(dependencies["*"], function(formula) {
      if (formula) {
        var f = dojo.indexOf(deps, formula);
        if (f !== -1) {
          deps.splice(f, 1);
          deps.push(formula);
        }
      }
    });
    return deps;

  },

  __calcAndSet: function(cell, d) {

    return dojo.hitch(this, function() {
      this.pane.setCellText(cell, null, dojo.hitch(this, d)())
    });

  },

  calcAll: function(dependencies) {
    var deps = [];
    for (var formula in this)
    if (formula.match(/^R\d+C\d+$/)) deps.push(formula);

    deps = this.tossDependencies(dependencies, deps);
    dojo.forEach(deps, dojo.hitch(this, function(dependency) {
      if (dependency) {
        var cell = this.cells ? this.cells.byId[dependency] : this.getCell(dependency);
        var d = this[dependency];
        if (d && cell)
        //          setTimeout(this.__calcAndSet(cell, d), 100);
        this.pane.setCellText(cell, null, dojo.hitch(this, d)());
      }
    }));
  }

});


dojo.declare("parus.templateGridPaneCloneMixin", [], {


  getCell: function(id) {
    var result = this.cells.byId[id];
    if (!result) result = this.table.pane.getCell(id);
    return result;
  },

  getCellValue: function(Row, Col, Ident, asString) {
    var valueNode;
    var cell;

    if (Row && Col) {
      var id = "R" + Row + "C" + Col;
      cell = this.getCell(id);
      valueNode = this.getValueNode(cell);
    }
    else if (Ident) {
      var staticValue = this.resolveCellIdent(Ident);
      if (staticValue) {
        valueNode = staticValue.valueNode;
        cell = staticValue.node;
      };
    };

    var text = parus.parus8.getTextContent(valueNode);

    if (!asString) {
      return dojo.number.parse(text) || 0;
    }
    else return text;

  },

  getCellNode: function(Row, Col, Ident) {
    var valueNode;
    var cell;

    if (Row && Col) {
      var id = "R" + Row + "C" + Col;
      cell = this.getCell(id);
    }
    else if (Ident) {
      var staticValue = this.resolveCellIdent(Ident);
      if (staticValue) {
        valueNode = staticValue.valueNode;
        cell = staticValue.node;
      };
    };

    return cell;

  },


  resolveCellIdent: function(Ident) {
    var result = null;
    dojo.forEach(this._staticValues, dojo.hitch(this, function(staticValue) {
      if ("TID_" + staticValue.balanceIndex == Ident) result = staticValue;
    }));
    if (!result) result = this.table.pane.resolveCellIdent(Ident);
    return result;
  },

  calcAll: function() {
    this.formulas.calcAll(this.dependencies);
    for (var formatCondition in this.formatConditions)
    dojo.hitch(this.formulas, this.formatConditions[formatCondition])();
  }

});


dojo.declare("parus.balanceTemplateGridExtraDictionaryDialog", [parus.dictionaryDialog], {

  gridChanged: function() {
    this.gridChange();
    if (this.grid.selection.getSelectedCount() <= 1) {
      this.cloneTable.attr("disabled", true);
      this.cloneTable.attr("checked", false);
      dojo.addClass(this.cloneTableLabel, "balanceReadOnlyHeader");
    }
    else {
      this.cloneTable.attr("disabled", false);
      dojo.removeClass(this.cloneTableLabel, "balanceReadOnlyHeader");
    }
  }

});


dojo.declare("parus.templateGridPaneNumberEdit", [dijit.form.NumberTextBox], {
  _getDisplayedValueAttr: function() {
    return this.textbox ? this.inherited(arguments) : null;
  },
  _getValueAttr: function() {
    return this.textbox ? this.inherited(arguments) : null;
  }
});


var oldclick = parus.designerDictEdit.prototype.dictButtonClick;


dojo.declare("parus.templateGridDesignerEdit", [parus.designerDictEdit], {

  dicts: null,

  showingDialog: false,

  subreport: null,

  autoComplete: true,

  onGetGridConditions: function() {

    var obj = this.inherited(arguments) || {};
    dojo.mixin(obj, {
      "IN_SUBREPORT": this.subreport
    });
    return obj;
  },

  _setInfo: function(unitCode, methodCode, inCode, outCode) {
    this.unitCode = unitCode;
    this.methodCode = methodCode;
    this.inCode = inCode;
    this.outCode = outCode;
    this.dictionaryInfoText = null;
    if (this.autoComplete) this._checkInfo();
  },

  postMixInProperties: function() {
    this.inherited(arguments);
    if (this.autoComplete) if (this.dicts.length == 1) {
      var dicParams = this.dicts[0].split("#");
      this._setInfo(dicParams[0], dicParams[1], dicParams[2], dicParams[3]);
    }
  },

  dictButtonClick: function() {

    if (this.showingDialog) return;

    if (this.showingDictionary) return;

    var args = arguments;
    var inherited = dojo.hitch(this, function() {
      oldclick.apply(this, arguments);
    });


    if (this.dicts.length == 1) {
      var dicParams = this.dicts[0].split("#");
      this._setInfo(dicParams[0], dicParams[1], dicParams[2], dicParams[3]);
      inherited();
    }
    else {

      var dialog = new parus.balanceUnitsDialog({
        unitcodes: dojo.map(this.dicts, function(d) {
          return d.split("#")[0];
        }),

        onApply: dojo.hitch(this, function() {

          var unitcode;
          var dict;

          dojo.forEach(dialog.unitsGrid.selection.getSelected(), function(item) {
            unitcode = dialog.unitsGrid.store.getValue(item, "UNITCODE", "");
          });

          if (unitcode) dojo.forEach(this.dicts, function(d) {
            if (d.split("#")[0] == unitcode) dict = d;
          });

          if (dict) {
            var dicParams = dict.split("#");
            this._setInfo(dicParams[0], dicParams[1], dicParams[2], dicParams[3]);
            setTimeout(inherited, 100);
            return true;
          }

          return true;
        }),

        onClose: dojo.hitch(this, function() {
          this.showingDialog = false;
        })
      });

      this.showingDialog = true;

      setTimeout(function() {
        dialog.show();
      }, 100);
    }
  }
});