﻿var fPSEditorIDSeed = 0;
// {
//   "DIV": html container, --required
//   "outputFormFieldName" : "fieldId"
//   "sets" :[],
//   "content": "{}",
//   "disabled": false,
//   "readonly": false,
//   "canAdd": true,
//   "canDel": true,
//   "canRaw": true,
//   "options" : {"n": {type : "text", plh: "Name"}, "d": {type : "textarea", plh: "Description"}},
//   "btnClasses" : {
//     "addBtnCls" : "class name",
//     "delBtnCls" : "class name",
//     "rawBtnCls" : "class name",
//     "clearBtnCls" : "class name",
//     "modalBtnCls" : "class name",
//   },
//   "texts" : {
//     "add-title" : "Add New Language",
//     "add-body" : "",
//     "raw-title" : "Raw Edit",
//     "raw-body" : "",
//     "clear-confirm-title" : "Confirm Clear",
//     "clear-confirm-body" : "Clear all language data?",
//     "del-confirm-title" : "Confirm Delete",
//     "del-confirm-body" : "",
//     "btn-del" : "Delete",
//     "btn-add" : "Add",
//     "btn-raw" : "Edit Raw",
//     "btn-clear" : "Clear",
//     "n-plh" : "Name",
//     "d-plh" : "Description",
//   }
// }
published.PropSetEditor = function (init) {
  if (typeof (init) === tUNDEFINED || init === null || typeof (init.DIV) === tUNDEFINED || init.DIV === null) throw "PropSetEditor.ctor(init.DIV)";

  var editor = this;
  WAVE.extend(editor, WAVE.EventManager);

  fPSEditorIDSeed++;
  var fDIV = init.DIV;
  var fContent = WAVE.memberClone(WAVE.tryParseJSON(init.content).obj);
  var fOutputFormFieldName = WAVE.strDefault(init.outputFormFieldName, null);
  var fReadOnly = WAVE.strAsBool(init.readonly, false);
  var fDisable = WAVE.strAsBool(init.disabled, false);
  var fCanRaw = WAVE.strAsBool(init.canRaw, true);
  var fCanAdd = WAVE.strAsBool(init.canAdd, true);
  var fCanDel = WAVE.strAsBool(init.canDel, true);
  var fSets =  WAVE.mergeArrays(["eng"], init.sets, function(a, b) { return a.toLowerCase() === b.toLowerCase(); }, function(a) { return a.toLowerCase(); });
  var fCurrentLocal = WAVE.strDefault(init.local, "eng");
  var fLocalizerSchema = "PSEditor";
  var fLocalizerField = "ps";
  var fTitle = WAVE.strDefault(init.title);
  var fSchema = WAVE.get(init, "schema", {n: {type: "text",plh: "Name"}, d: {type : "textarea", plh: "Description"}});

  var fClasses = WAVE.get(init, "btnClasses", {});
    fClasses.addBtnCls = WAVE.strDefault(fClasses.addBtnCls, published.CLS_PS_BTN_ADD);
    fClasses.delBtnCls = WAVE.strDefault(fClasses.delBtnCls, published.CLS_PS_BTN_DEL);
    fClasses.rawBtnCls = WAVE.strDefault(fClasses.rawBtnCls, published.CLS_PS_BTN_RAW);
    fClasses.clearBtnCls = WAVE.strDefault(fClasses.clearBtnCls, published.CLS_PS_BTN_CLEAR);
    fClasses.modalBtnCls = WAVE.strDefault(fClasses.modalBtnCls, "");

  var fSeed = "ps_" + fPSEditorIDSeed;
  var fControlIds = {
    btnAddId : "addLang_" + fSeed,
    btnRawId : "rawEdit_" + fSeed,
    btnClearId : "clearBtn_" + fSeed,
    divTextTemplateId : "textTemplate_" + fSeed,
    divEditorsContainerId : "divEditorsContainer_" + fSeed,
    divDeleteButtonId : "deleteButtonId_" + fSeed,
    inputId : "_inputId_" + fSeed,
    divLangNameId : "islLabel_" + fSeed,
    outputHiddenId : "hidden_" + fSeed
  };

  var fTexts = WAVE.get(init, "texts", {});
    fTexts.addTitle = getText("add-title", "Add New Language");
    fTexts.addBody = getText("add-body", "");
    fTexts.rawTitle= getText("raw-title", "Raw Edit");
    fTexts.rawBody = getText("raw-body");
    fTexts.clearConfirmTitle = getText("clear-confirm-title", "Confirm Clear");
    fTexts.clearConfirmBody = getText("clear-confirm-body", "Clear all language data?");
    fTexts.delConfirmTitle = getText("del-confirm-title", "Confirm Delete");
    fTexts.delConfirmBody = getText("del-confirm-body");
    fTexts.btnDel = getText("btn-del", "Delete");
    fTexts.btnAdd = getText("btn-add", "Add");
    fTexts.btnRaw = getText("btn-raw", "Edit Raw");
    fTexts.btnClear = getText("btn-clear", "Clear");

  function getText(n, dflt){
    return localize(fTexts[n], dflt);
  }

  function localize(text, dflt){
    return WAVE.strLocalize(fCurrentLocal, fLocalizerSchema, fLocalizerField, WAVE.strDefault(text, dflt));
  }

  function getNotAddedLangs() {
    var langs = [];
    for (var l in fSets) {
      if (!WAVE.has(fContent, fSets[l]))
        langs.push(fSets[l]);
    }
    return langs;
  }

  function addMainControls() {
    var addControlTemaplate =
      "<input id='@outerId@' type='hidden' name='@outerName@'/>" +
      "<div id='@divEditorsContainerId@' class='@divEditorsContainerClass@'></div>" +
      ((!fReadOnly && !fDisable) ?
        (fCanAdd ? "<input type='button' id='@btnAddId@' class='@btnAddClass@' value='@add@' />" : "") +
        (fCanRaw ? "<input type='button' id='@btnRawId@' class='@btnRawClass@' value='@raw@' />" : "") +
        (fCanDel ? "<input type='button' id='@btnClearId@' class='@btnClearClass@' value='@clear@' />" : "") : "");

    fDIV.innerHTML = WAVE.strHTMLTemplate(addControlTemaplate,
      {
        outerId: fControlIds.outputHiddenId,
        outerName: WAVE.strDefault(fOutputFormFieldName, ''),
        divEditorsContainerId: fControlIds.divEditorsContainerId,
        divEditorsContainerClass: published.CLS_PS_DIV_LANGS_CONTAINER,
        btnAddId: fControlIds.btnAddId,
        btnAddClass: fClasses.addBtnCls,
        btnRawId: fControlIds.btnRawId,
        btnRawClass: fClasses.rawBtnCls,
        btnClearId: fControlIds.btnClearId,
        btnClearClass: fClasses.clearBtnCls,

        add: fTexts.btnAdd,
        raw: fTexts.btnRaw,
        clear: fTexts.btnClear
      });
    if (!fReadOnly && !fDisable && fCanAdd && getNotAddedLangs().length === 0)
      WAVE.id(fControlIds.btnAddId).disabled = true;

    if (fReadOnly || fDisable) return;

    if (fCanAdd && getNotAddedLangs().length > 0) {
      WAVE.id(fControlIds.btnAddId).onclick = function () {
        var btnAdd = this;
        var ls = getNotAddedLangs();
        var opts = "";
        for (var l in ls) {
          opts += "<option>" + ls[l] + "</option>";
        }

        var inputId = "newIso_" + fSeed;
        published.showConfirmationDialog(
          pfxTitle() + fTexts.addTitle,
          "<div>" + fTexts.addBody + "</div>" +
          "<div><select class='" + published.CLS_PS_LANG_SELECTOR + "' id='" + inputId + "'>" + opts + "</select></div>",
          [published.DLG_OK, published.DLG_CANCEL],
          function (sender, result) {
            if (result === published.DLG_OK) {
              var iso = WAVE.id(inputId).value;
              editor.addLang(iso);
              if (ls.length === 1)
                btnAdd.disabled = true;
            }
            return true;
          },
          { btnCls: fClasses.modalBtnCls });
        WAVE.id(inputId).focus();
      };
    }

    if (fCanRaw) {
      WAVE.id(fControlIds.btnRawId).onclick = function () {
        var inputId = "raw" + fSeed;
        published.showConfirmationDialog(
          pfxTitle() + fTexts.rawTitle,
          "<div>" + fTexts.rawBody + "</div>" +
          "<div><textarea style='width: 70vw; height: 70vh;' class='" + published.CLS_PS_TEXTAREA_RAW_EDITOR + "' type='text' id='" + inputId + "'></textarea></div>",
          [published.DLG_OK, published.DLG_CANCEL],
          function (sender, result) {
            if (result === published.DLG_OK) {
              var val = WAVE.id(inputId).value;
              var res = WAVE.tryParseJSON(val);
              if (res.ok){
                  if (WAVE.checkKeysUnique(res.obj)){
                    published.toast(WAVE.strLocalize(fCurrentLocal, fLocalizerSchema, fLocalizerField, "JSON is valid, but some keys are duplicated"), "error");
                    return false;
                  }
                  editor.content(val);
                }
              else {
                published.toast(WAVE.strLocalize(fCurrentLocal, fLocalizerSchema, fLocalizerField, "Invalid JSON"), "error");
                return false;
              }
            }
            return true;
          },
          { btnCls: fClasses.modalBtnCls });
        WAVE.id(inputId).value = editor.content();
        WAVE.id(inputId).focus();
      };
    }

    if (fCanDel) {
      WAVE.id(fControlIds.btnClearId).onclick = function () {
        published.showConfirmationDialog(
          pfxTitle() + fTexts.clearConfirmTitle,
          "<div>"+fTexts.clearConfirmBody+"</div>",
          [published.DLG_OK, published.DLG_CANCEL],
          function (sender, result) {
            if (result === published.DLG_OK) {
              editor.clear();
            }
            return true;
          },
          { btnCls: fClasses.modalBtnCls });
      };
    }
  }

  function getLangContainerId(iso){
    return  fSeed + "_" + iso;
  }

  function buildLang(iso) {
    var langId = getLangContainerId(iso);
    var langEditors = WAVE.id(fControlIds.divEditorsContainerId);
    var delButtonId = fControlIds.divDeleteButtonId + "_" + iso;
    var labelId = fControlIds.divLangNameId + "_" + iso;
    var inputId = fControlIds.inputId + "_" + iso;
    var controlContainerId = fControlIds.divTextTemplateId + "_" + iso;

    function uName(filedName, id){
      return filedName + id;
    }

    var html =
      "<fieldset id='@langId@'>" +
      "<legend id='@isoLabelId@' class='@langClass@'></legend>" +
      "<div class='@textEditorsContainerClass@' id='@controlContainerId@'>" +
      "</div>" +
      (fCanDel && !fReadOnly && !fDisable ? "<input type='button' id='@deleteButtonId@' class='@delCls@' value='@delText@'/>" : "") +
      "</fieldset>";

    var params = {
        langId: langId,
        controlContainerId: controlContainerId,
        deleteButtonId: delButtonId,
        isoLabelId: labelId,
        langClass: published.CLS_PS_DIV_LANG_NAME,
        labelContainerClass: published.CLS_PS_LABEL_CONTAINER,
        textEditorsContainerClass: published.CLS_PS_INPUT_CONTAINER,
        delCls: fClasses.delBtnCls,
        disabled: fDisable ? "disabled" : "",
        readonly: fReadOnly ? "readonly" : "",

        delText: fTexts.btnDel
      };

    langEditors.insertAdjacentHTML("beforeend", WAVE.strHTMLTemplate(html, params));
    WAVE.id(labelId).innerText = iso;

    var ed = new published.ObjectEditor({
      DIV: WAVE.id(controlContainerId),
      meta: {
        type: "object",
        schema: fSchema
      },
      content: fContent[iso],
      disabled : fDisable,
      readonly : fReadOnly
    });

    ed.eventBind(published.EVT_OBJECT_EDITOR_UPDATED, function (e, d) {
      fContent[iso] = d;
      editor.content(JSON.stringify(fContent), false);
    });

    if (fCanDel && !fReadOnly && !fDisable) {
      WAVE.id(delButtonId).onclick = function () {
        published.showConfirmationDialog(
          pfxTitle() + fTexts.delConfirmTitle + " : " + iso.toUpperCase(),
          "<div>"+fTexts.delConfirmBody+"</div>",
          [published.DLG_OK, published.DLG_CANCEL],
          function (sender, result) {
            if (result === published.DLG_OK) {
              editor.deleteLang(iso);
            }
            return true;
          },
          { btnCls: fClasses.modalBtnCls });
      };
    }
  }

  function buildEditors() {
    if (WAVE.isObject(fContent))
      for (var iso in fContent) buildLang(iso);
  }

  function rebuild() {
    while (fDIV.hasChildNodes()) {
      fDIV.removeChild(fDIV.lastChild);
    }
    addMainControls();
    buildEditors();
    setHiddenValue();
  }

  function setHiddenValue(){
      if (fOutputFormFieldName !== null) WAVE.id(fControlIds.outputHiddenId).value = editor.content();
  }

  addMainControls();

  this.DIV = function() { return fDIV; };

  this.jsonContent = function () { return fContent; };

  this.content = function (value, rebuild) {
    if (typeof (value) === tUNDEFINED)
      return WAVE.empty(fContent) ? "" : JSON.stringify(fContent, null, 2);

    var parsed = WAVE.tryParseJSON(value);
    if (parsed.ok) {
      rebuild = WAVE.strAsBool(rebuild, true);
      if (rebuild) {
        for (var iso in fContent) {
          WAVE.removeElem(getLangContainerId(iso));
        }
      }

      fContent = WAVE.memberClone(parsed.obj);

      if(rebuild) buildEditors();

      setHiddenValue();
      editor.eventInvoke(published.EVT_PS_EDITOR_UPDATED, fContent);
    }
    return value;
  };

  this.title = function(value) {
      if (typeof (value) === tUNDEFINED) return fTitle;
      fTitle = WAVE.strDefault(value);
  };

  function pfxTitle(){
    return WAVE.strEmpty(fTitle) ? "" : (fTitle + ": ");
  }

  this.enable = function (value) {
    if (typeof(value) === tUNDEFINED) return !fDisable;

    fDisable = !(value===true);
    rebuild();
    return value;
  };

  this.readOnly = function (value) {
    if (typeof(value) === tUNDEFINED) return fReadOnly;

    fReadOnly = value===true;
    rebuild();
    return value;
  };

  this.canAdd = function (value) {
    if (typeof(value) === tUNDEFINED) return fCanAdd;

    fCanAdd = value===true;
    rebuild();
    return value;
  };

  this.canDel = function (value) {
    if (typeof(value) === tUNDEFINED) return fCanDel;

    fCanDel = value===true;
    rebuild();
    return value;
  };

  this.canRaw = function (value) {
    if (typeof (value) === tUNDEFINED) return fCanRaw;

    fCanRaw = value===true;
    rebuild();
    return value;
  };

  this.addLang = function (iso) {
    if (WAVE.strEmpty(iso)) return false;

    iso = iso.toLowerCase();
    if (WAVE.has(fContent, iso)) return false;

    fContent[iso] = {};
    buildLang(iso);

    editor.content(JSON.stringify(fContent));
    return true;
  };

  this.deleteLang = function (iso) {
    if (WAVE.strEmpty(iso)) return false;

    iso = iso.toLowerCase();
    if (!WAVE.has(fContent, iso)) return false;

    delete fContent[iso];
    WAVE.removeElem(getLangContainerId(iso));
    if (!fReadOnly && !fDisable) WAVE.id(fControlIds.btnAddId).disabled = false;
    editor.content(JSON.stringify(fContent));
    return true;
  };

  this.clear = function () {
    if (!fReadOnly && !fDisable) WAVE.id(fControlIds.btnAddId).disabled = false;
    editor.content("{}");
  };

  rebuild();
  return editor;
};//PropSetEditor