fcf.module({
  name: "fcfManagement:templates/pages/translations/translations-tab.wrapper.js",
  dependencies: ["fcf:NClient/Wrapper.js"],
  module: function(Wrapper){
    return class WrapperEx extends Wrapper{
      
      constructor(a_initializeOptions){
        super(a_initializeOptions);
        let displayedFilesAll = this.getArg("displayedFilesAll");
        this._editableFiles = {};
        for(let language in displayedFilesAll){
          for(let i = 0; i < displayedFilesAll[language].length; ++i)
            if (displayedFilesAll[language][i].editable)
              this._editableFiles[language] = displayedFilesAll[language][i].path;
        }
        this._counter = Math.floor(Number.MAX_SAFE_INTEGER/2);
      }

      onArg (a_argName, a_value, a_editor, a_isInnerCall, a_suffix) {
        if (a_argName == 'translations' || a_argName == 'translationsModify'){
          if (!this.getChild("save").getArg("enable")) {
            this.getChild("save").setArg("enable", true);
            this.getChild("cancel").setArg("enable", true);
          }
          return;
        }
        this.update();
      }

      onArgTranslations(a_value, a_editor, a_isInnerCall, a_suffix){
        let translationsModify = this.getArg("translationsModify");
        let address = fcf.parseObjectAddress(a_suffix);
        if (address.length < 3)
          return;
        let t = a_value[address[0]][address[1]];
        if (!t)
          return;

        let modifyData = t.modify !== true || t.path !== this._editableFiles[address[0]];

        t.modify = true;
        t.path   = this._editableFiles[address[0]];
        translationsModify[address[0]][t.phrase] = t;
        this.setArg("translationsModify", translationsModify);
        if (modifyData){
          this.setArg(`translations["${address[0]}"]["${address[1]}"].modify`, t.modify);
          this.setArg(`translations["${address[0]}"]["${address[1]}"].path`, t.path);
        }
      }

      onAppendRecord() {
        fcf.application.render({
          template: "@controls:dialog",
          parent:   this,
          args: {
            fcfStyle: "max-width: 400px; width: 100%",
            title:    fcf.t("Append record"),
            content:  fcf.argTmpl("@controls:form", {
              fcfAlias: "form",
              fields: [
                {
                  alias:    "phrase",
                  title:    fcf.t("Phrase"),
                  type:     "text",
                  notEmpty: true,
                  args:     { height: "4em", autofocus: true, }
                },
                {
                  alias:    "language",
                  title:    fcf.t("Language"),
                  type:     "text",
                  template: "@controls:select",
                  args:     { items: this.getArg("languages"), value: this.getArg("defaultLanguage") },
                }
              ]
            }),
            buttons: fcf.argVal([
              fcf.argTmpl("@controls:button", {title: fcf.t("Ok"), fcfEventClick:"parent.close('ok')"}),
              fcf.argTmpl("@controls:button", {title: fcf.t("Cancel"), fcfEventClick:"parent.close('cancel')"}),
            ]),
            fcfEventClose: "parent.onAppendCloseDialog(event)"

          },
        })
      }

      onAppendCloseDialog(event){
        if (event.reason == "cancel")
          return;

        let form = event.wrapper.getChild("form");
        let phraseLanguage = form.getArg("value.language");
        let errors = form.check();
        if (!fcf.empty(errors)){
          form.setArg("errors", errors);
          event.preventDefault();
          return;
        }

        let translationsModify = this.getArg("translationsModify");
        let displayedFilesAll = this.getArg("displayedFilesAll");
        for(let language in displayedFilesAll) {
          if (phraseLanguage == language)
            continue;

          for (let i = 0; i < displayedFilesAll[language].length; ++i) {
            if (displayedFilesAll[language][i].editable){
              let ts = {};
              let phrase = form.getArg("value").phrase;
              ts[phrase] = {
                phrase:    phrase,
                translate: phrase,
                path:      displayedFilesAll[language][i].path,
                weight:    ++this._counter,
              };
              if (phrase in this.getArg("translationsModify")[language])
                this.getArg("translationsModify")[language][phrase] = ts[phrase];
              else
                translationsModify[language] = fcf.append(ts, this.getArg("translationsModify")[language]);
            }
          }
        }
        this.setArg("translationsModify", translationsModify);
        this._rebuildTranslations();
      }

      onRemoveRecord(a_key){
        let language           = this.getArg("language");
        let translations       = this.getArg("translations");
        let translationsOrigin = this.getArg("translationsOrigin");
        let translationsModify = this.getArg("translationsModify");
        let displayedFilesAll  = this.getArg("displayedFilesAll");

        let t = translations[this.getArg("language")][a_key];
        delete translationsModify[this.getArg("language")][t.phrase];
        if (translations[language]) {
          for(let i = 0; i < displayedFilesAll[language].length; ++i){
            if (!displayedFilesAll[language][i].editable)
              continue;
            if (!translationsOrigin[language] || !translationsOrigin[language][displayedFilesAll[language][i].path] )
              continue;
            let ts = translationsOrigin[language][displayedFilesAll[language][i].path];
            let newTs = [];
            for(let i = 0; i < ts.length; ++i) {
              if (ts[i].phrase != t.phrase)
                newTs.push(ts[i]);
            }
            translationsOrigin[language][displayedFilesAll[language][i].path] = newTs;
          }
        }
        this.setArg("translationsModify", translationsModify, false);
        this.setArg("translationsOrigin", translationsOrigin, false);
        this._rebuildTranslations();        
      }

      onSave(){
        this.getChild("save").setArg("enable", false);
        this.getChild("cancel").setArg("enable", false);
        let translationsOrigin = this.getArg("translationsOrigin");
        let translationsModify = this.getArg("translationsModify");
        let modify = {};
        for(let language in translationsOrigin) {
          modify[language] = {
            language: language,
            translations: {}
          };
          for(let phrase in translationsModify[language]) {
            let t = translationsModify[language][phrase];
            modify[language].translations[t.phrase] = t.translate;
          }
          if (this._editableFiles[language]) {
            for(let index = 0; index < translationsOrigin[language][this._editableFiles[language]].length; ++index) {
              let t = translationsOrigin[language][this._editableFiles[language]][index];
              if (!(t.phrase in modify[language].translations))
                modify[language].translations[t.phrase] = t.translate;
            }
          }
        }

        this.send({
          files:  this._editableFiles,
          modify: modify,
        });
      }

      onCancel(){
        this.getChild("save").setArg("enable", false);
        this.getChild("cancel").setArg("enable", false);
        this.reload();
      }

      onFileClick(a_path){
        let displayedFilesAll = this.getArg("displayedFilesAll");
        let displayedFiles = this.getArg("displayedFiles");
        let file = displayedFiles[fcf.find(displayedFiles, (k, file)=>{ return file.path == a_path})];
        if (!file)
          return;
        file.enable = !file.enable;

        let displayedFilesMap = {};
        for(let language in displayedFilesAll) {
          displayedFilesMap[language] = {};
          for(let i = 0; i < displayedFilesAll[language].length; ++i) {
            if (displayedFilesAll[language][i].enable)
              displayedFilesMap[language][displayedFilesAll[language][i].path] = displayedFilesAll[language][i]
          }
        }
        let translationsModify = this.getArg("translationsModify");
        let translationsOrigin = this.getArg("translationsOrigin");

        let mapTranslations = {};
        let newTranslations = {};
        for(let language in translationsOrigin) {
          newTranslations[language] = [];
          mapTranslations[language] = {};
          let ei = [];
          for(let fileIndex = 0; fileIndex < displayedFilesAll[language].length; ++fileIndex){
            let filePath = displayedFilesAll[language][fileIndex].path;
            if (!displayedFilesAll[language][fileIndex].enable)
              continue;
            for(let i = 0; i < translationsOrigin[language][filePath].length; ++i) {
              let t = translationsOrigin[language][filePath][i];
              if (t.phrase in mapTranslations[language]){
                newTranslations[language][mapTranslations[language][t.phrase]] = t;
              } else {
                mapTranslations[language][t.phrase] = newTranslations[language].length;
                newTranslations[language].push(t);
              }
            }
          }

          for(let prase in translationsModify[language]){
            let t = translationsModify[language][prase];
            if (t.phrase in mapTranslations[language]){
              newTranslations[language][mapTranslations[language][t.phrase]] = t;
            } else {
              newTranslations[language].push(t);
            }
          }

          newTranslations[language].sort((a_left, a_right)=>{
            return a_right.weight - a_left.weight;
          })
        }

        this.setArg("translations", newTranslations, true);
        this.setArg("displayedFiles", displayedFiles);
      }

      _rebuildTranslations(){
        let displayedFilesAll = this.getArg("displayedFilesAll");
        let displayedFiles = this.getArg("displayedFiles");
        let displayedFilesMap = {};
        for(let language in displayedFilesAll) {
          displayedFilesMap[language] = {};
          for(let i = 0; i < displayedFilesAll[language].length; ++i) {
            if (displayedFilesAll[language][i].enable)
              displayedFilesMap[language][displayedFilesAll[language][i].path] = displayedFilesAll[language][i]
          }
        }
        let translationsModify = this.getArg("translationsModify");
        let translationsOrigin = this.getArg("translationsOrigin");
        
        let mapTranslations = {};
        let newTranslations = {};
        for(let language in translationsOrigin) {
          newTranslations[language] = [];
          mapTranslations[language] = {};
          let ei = [];
          for(let fileIndex = 0; fileIndex < displayedFilesAll[language].length; ++fileIndex){
            let filePath = displayedFilesAll[language][fileIndex].path;
            if (!displayedFilesAll[language][fileIndex].enable)
              continue;
            for(let i = 0; i < translationsOrigin[language][filePath].length; ++i) {
              let t = translationsOrigin[language][filePath][i];
              if (t.phrase in mapTranslations[language]){
                newTranslations[language][mapTranslations[language][t.phrase]] = t;
              } else {
                mapTranslations[language][t.phrase] = newTranslations[language].length;
                newTranslations[language].push(t);
              }
            }
          }

          for(let prase in translationsModify[language]){
            let t = translationsModify[language][prase];
            if (t.phrase in mapTranslations[language]){
              newTranslations[language][mapTranslations[language][t.phrase]] = t;
            } else {
              newTranslations[language].push(t);
            }
          }

          newTranslations[language].sort((a_left, a_right)=>{
            return a_right.weight - a_left.weight;
          });
        }
        
        this.setArg("translations", newTranslations, false);
        this.update();
      }


    };
  }
});
