!function(i){i.widget("ih.resizableColumns",{_create:function(){this._initResizable()},_initResizable:function(){let e,t,n,s=this.element;s.find("th").resizable({handles:{e:" .resizeHelper"},minWidth:10,create:function(e,t){let n=i(this).find(".columnLabel").width();n&&(n+=i(this).find(".ui-resizable-e").width(),i(this).resizable("option","minWidth",n))},start:function(i,h){let l=h.helper.index()+1;e=s.find("colgroup > col:nth-child("+l+")"),t=parseInt(e.get(0).style.width,10),n=h.size.width},resize:function(s,h){let l=h.size.width-n,d=t+l;e.width(d),i(this).css("height","auto")}})}})}(jQuery);

$.getScript("https://cdnjs.cloudflare.com/ajax/libs/alasql/0.6.1/alasql.min.js");

const compContainer = $(`#${comp.code}`);
const tableContainer = compContainer.find('.exp-table-container');

const formatDate = () => {
  let d = new Date();
  return ['0' + d.getDate(), '0' + (d.getMonth() + 1), '' + d.getFullYear()].map(x => x.slice(-2)).join('.');
}

const getSystemReport = () => {
  Cons.showLoader();
  AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/registry/filters?registryCode=${registryTable.registryCode}&type=service`)
  .then(filters => {
    let filterID = filters.find(x => x.code === registryTable.filterCode);
    if(filterID) filterID = filterID.id;
    Cons.hideLoader();

    let url = `${window.location.origin}/Synergy/rest/reg/load/xls?r=${registryTable.registryID}`;
    url += `&l=ru&f=${filterID || ''}&s=&u=${AS.OPTIONS.currentUser.userid}&fn=${registryTable.registryName}_${formatDate()}`;
    window.open(url);
  });
}

const getRegistryList = async () => {
  const {registryList} = Cons.getAppStore();
  return new Promise(async resolve => {
    if(registryList) {
      resolve(registryList);
    } else {
      const list = await appAPI.getRegistryList();
      list ? resolve(UTILS.parseRegistryList(list)) : resolve(null);
    }
  });
}

const Paginator = {
  container: $('<div class="exp-pt-container">'),
  paginator: $('<div class="exp-pt-paginator">'),
  pContent: $('<div class="exp-pt-paginator-content">'),
  bPrevious: $('<button class="exp-pt-previous" disabled="disabled" title="Назад">'),
  bNext: $('<button class="exp-pt-next" disabled="disabled" title="Вперед">'),
  label: $('<label>'),
  input: $('<input type="text">'),
  countInPart: 0,
  rows: 0,
  currentPage: 1,
  pages: 0,

  init: function(){
    $('.exp-pt-container').remove();
    $('.exp-registry-container').after(this.container);
    this.pContent.append(this.label).append(this.input);
    this.paginator.append(this.bPrevious).append(this.pContent).append(this.bNext);
    this.container.append(this.paginator);
    this.reset();

    this.bNext.click(() => {
      this.currentPage++;
      this.update();
      registryTable.createBody();
    });

    this.bPrevious.click(() => {
      this.currentPage--;
      this.update();
      registryTable.createBody();
    });

    this.label.on('dblclick', e => {
      e.preventDefault();
      this.input.show();
      this.label.hide();

      this.input.on('blur', () => {
        this.label.show();
        this.input.hide();
      });

      this.input.val("" + this.currentPage);

      this.input.on('keypress', e => {
        if (e.which != 8 && e.which != 0 && e.which != 46 && (e.which < 48 || e.which > 57)) return false;
      });

      this.input.on('keydown', e => {
        if(e.which === 13) {
          let inputVal = +this.input.val();
          if(inputVal && inputVal != this.currentPage && inputVal <= this.pages && inputVal >= 1){
            this.currentPage = inputVal;
            this.update();
            registryTable.createBody();
          }
          this.label.show();
          this.input.hide();
          this.input.off();
        }
      });
      this.input.focus();
    });

  },

  update: function(){
    this.pages = Math.ceil(this.rows / this.countInPart),
    this.label.text(this.currentPage + ' / ' + this.pages);

    if(this.pages == 0) {
      this.bPrevious.attr('disabled', 'disabled');
      this.bNext.attr('disabled', 'disabled');
    } else {
      if(this.currentPage == 1) {
        this.bPrevious.attr('disabled', 'disabled');
        if (this.currentPage == this.pages) {
          this.bNext.attr('disabled', 'disabled');
        } else {
          this.bNext.removeAttr('disabled');
        }
      } else {
        this.bPrevious.removeAttr('disabled');
        if (this.currentPage == this.pages) {
          this.bNext.attr('disabled', 'disabled');
        } else {
          this.bNext.removeAttr('disabled');
        }
      }
    }
  },

  reset: function(){
    this.countInPart = 15;
    this.rows = 15;
    this.currentPage = 1;
    this.pages = 0;
  }
}

const registryTable = {
  registryInfo: null,
  registryCode: null,
  registryID: null,
  registryName: '',
  registryRights: [],
  filterCode: null,
  formCode: null,

  selectedItems: [],

  searchString: null,
  filterSearchUrl: null,

  allRights: [],

  sortCmpID: null,
  sortDesc: false,
  searchField: null,
  searchValue: null,
  heads: [],

  registryTable: null,
  colgroup: null,
  tHead: null,
  tBody: null,

  isDelete: false,

  getNextFieldNumber: function(url) {
    let p = url.substring(url.indexOf('?') + 1).split('&');
    p = p.map(x => {
      x = x.split('=');
      if(x[0].indexOf('field') !== -1 && x[0] !== 'fields') return x[0];
    }).filter(x => x).sort();
    if(p.length) return Number(p[p.length - 1].substring(5)) + 1;
    return '';
  },

  getUrl: function(all){
    let url = `api/registry/data_ext?registryCode=${this.registryCode}`;
    if(!all) url += `&pageNumber=${Paginator.currentPage - 1}&countInPart=${Paginator.countInPart}`;
    if(this.filterCode) url+=`&filterCode=${this.filterCode}`;
    if(this.heads && this.heads.length > 0) this.heads.forEach(item => url+=`&fields=${item.columnID}`);
    if(this.sortCmpID) url+=`&sortCmpID=${this.sortCmpID}&sortDesc=${this.sortDesc}`;
    if(this.searchString) url += `&searchString=${this.searchString}`;
    if(this.filterSearchUrl) {
      url += this.filterSearchUrl;
      if(this.searchField && this.searchValue) {
        let next = this.getNextFieldNumber(this.filterSearchUrl);
        url+=`&field${next}=${this.searchField}&condition${next}=CONTAINS&value${next}=${this.searchValue}`;
      }
    } else {
      if(this.searchField && this.searchValue) url+=`&field=${this.searchField}&condition=CONTAINS&value=${this.searchValue}`;
    }
    return url;
  },

  removeRegistryRow: function(uuid, e) {
    e.preventDefault();
    e.target.blur();
    UIkit.modal.confirm(i18n.tr('Вы действительно хотите удалить запись реестра?'), {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}}).then(() => {
      Cons.showLoader();
      try {
        rest.synergyGet(`api/registry/delete_doc?dataUUID=${uuid}`, res => {
          if(res.errorCode != '0') throw new Error(res.errorMessage);
          showMessage(i18n.tr("Запись реестра удалена"), "success");
          this.createBody();
          Cons.hideLoader();
        });
      } catch (err) {
        Cons.hideLoader();
        showMessage(i18n.tr("Произошла ошибка при удалении записи реестра"), "error");
        console.log(error);
      }
    }, () => null);
  },

  documentInfo: function(dataRow, e){
    const createRow = (label, value) => $(`<tr><td>${label}</td><td>${value}</td></tr>`);

    let dialog = $('<div class="uk-flex-top" uk-modal>');
    let md = $('<div class="uk-modal-dialog uk-margin-auto-vertical">');
    let modalBody = $('<div class="uk-modal-body" uk-overflow-auto>');

    dialog.append(md);
    md.append('<button class="uk-modal-close-default" type="button" uk-close></button>')
    .append('<div class="uk-modal-header"><h2 class="uk-modal-title">Свойства документа</h2></div>')
    .append(modalBody)
    .append('<div class="uk-modal-footer uk-text-right"><button class="uk-button uk-button-default uk-modal-close" type="button">Закрыть</button></div>');

    Cons.showLoader();
    try {
      rest.synergyGet(`api/docflow/doc/document_info?documentID=${dataRow.documentID}`, info => {
        let container = $('<div>');
        let table = $('<table>', {class: 'uk-table doc-info'});
        let body = $('<tbody>');
        let thead = $('<thead>').append('<tr><th>Параметр</th><th>Значение</th></tr>');

        body.append(createRow('Наименование реестра', info.registryName));
        body.append(createRow('Наименование формы', info.formName));
        body.append(createRow('Автор документа', info.author));
        body.append(createRow('Дата создания', info.createDate));
        body.append(createRow('documentID', info.documentID));
        body.append(createRow('asfDataID', info.asfDataID));

        table.append(thead).append(body);
        container.append(table);
        modalBody.append(container);
        Cons.hideLoader();
      });
    } catch (err) {
      Cons.hideLoader();
      modalBody.append('<p>Произошла ошибка получения данных по документу</p>');
      console.log(error);
    }

    e.preventDefault();
    e.target.blur();
    UIkit.modal(dialog).show();
    dialog.on('hidden', () => dialog.remove());
  },

  openDocument: function(dataRow, updateData = false) {
    Cons.setAppStore({dataRow: dataRow});
    if(this.allRights.includes('rr_read') || this.allRights.includes('rr_edit')) {
      if(updateData) {
        openFormPlayer(dataRow.dataUUID, null, () => {
          this.createBody();
        });
      } else {
        openFormPlayer(dataRow.dataUUID);
      }
    } else {
      showMessage(i18n.tr('У вас нет прав на просмотр этого документа'), 'warning');
    }
  },

  contextMenu: function(el, dataRow){
    this.isDelete = false;
    if(this.allRights.indexOf('rr_delete') !== -1 && dataRow.status != 'STATE_NOT_FINISHED') {
      this.isDelete = true;
    }
    el.on('contextmenu', event => {
      $('.exp-context-menu').remove();
      $('<div>', {class: 'exp-context-menu'})
      .css({
        "left": event.pageX + 'px',
        "top": event.pageY + 'px'
      })
      .appendTo('body')
      .append(
        $('<ul class="uk-nav-default uk-nav-parent-icon" uk-nav>')
        .append($(`<li ><a href="javascript:void(0);"><span class="uk-margin-small-right" uk-icon="icon: push"></span>Открыть</a></li>`)
          .on('click', e => {
            this.openDocument(dataRow, true);
          })
        )
        .append($('<li><a href="javascript:void(0);"><span class="uk-margin-small-right" uk-icon="icon: info"></span>Информация</a></li>')
          .on('click', e => this.documentInfo(dataRow, e))
        )
        .append('<li class="uk-nav-divider"></li>')
        .append($(`<li ${this.isDelete ? '' : 'class="uk-disabled"'} ><a href="javascript:void(0);"><span class="uk-margin-small-right" uk-icon="icon: trash"></span>Удалить запись</a></li>`)
          .on('click', e => {
            this.isDelete ? this.removeRegistryRow(dataRow.dataUUID, e) : false;
          })
        )
      )
      .show('fast');
      return false;
    });
  },

  createRow: function(dataRow) {
    const {documentID, fieldValue, status} = dataRow;
    const tr = $('<tr>');

    const checkbox = $('<input/>').addClass('uk-checkbox').attr('type', 'checkbox');
    const tmpTd = $('<td>');
    if(this.selectedItems.indexOf(documentID) !== -1) checkbox.prop('checked', true);
    tmpTd.append(`<span class="mobile-table-header">Выбор</span>`).append(checkbox);

    const statusRow = $(`<td class="registry_status_row" statusrow="${status}">`);

    switch (status) {
      case "STATE_SUCCESSFUL": statusRow.append(`<span uk-icon="icon: check"></span>`); break;
      case "STATE_NOT_FINISHED": statusRow.append(`<span uk-icon="icon: future"></span>`); break;
      case "STATE_UNSUCCESSFUL": statusRow.append(`<span uk-icon="icon: ban"></span>`); break;
      default: statusRow.append(`<span uk-icon="icon: file-text"></span>`);
    }

    tr.append(statusRow, tmpTd);

    checkbox.on('change', e => {
      if(e.target.checked) {
        if(this.selectedItems.indexOf(documentID) === -1) {
          this.selectedItems.push(documentID);
        }
      } else {
        const index = this.selectedItems.indexOf(documentID);
        if(index !== -1) this.selectedItems.splice(index, 1);
      }
      if(this.selectedItems.length > 0) {
        $('.action-menu-item').removeClass('uk-disabled');
        if($('.action-menu-item.item-delete').length) {
          if(!this.isDelete) $('.action-menu-item.item-delete').addClass('uk-disabled');
        }
      } else {
        $('.action-menu-item').addClass('uk-disabled');
      }
    });

    this.heads.forEach(item => {
      const td = $('<td>');
      if (fieldValue.hasOwnProperty(item.columnID)) {
        td.attr('uk-tooltip', `title: ${fieldValue[item.columnID]}; duration: 300;`);
        td.append(`<span class="mobile-table-header">${item.label}</span>`);
        td.append(`<span>${fieldValue[item.columnID]}</span>`);
      }
      tr.append(td);
    });

    this.contextMenu(tr, dataRow);

    tr.on('click', e => {
      if($(e.target).is("input")) return;
      this.openDocument(dataRow, true);
    });

    return tr;
  },

  createBody: function() {
    try {
      this.updateRigths();
      if(!this.allRights.includes("rr_list")) throw new Error(`Нет прав на просмотр данного реестра`);

      rest.synergyGet(this.getUrl(), data => {
        this.tBody.empty();
        if(data.errorCode && data.errorCode != 0) {
          Paginator.rows = 0;
        } else {
          data.result.forEach(item => this.tBody.append(this.createRow(item)));
          Paginator.rows = data.recordsCount;
        }
        this.calcSum();
        Paginator.update();
        tableContainer.scrollTop(0);
      });
    } catch (err) {
      console.log('ERROR registryList createBody', err);
      showMessage(err.message, 'error');
    }
  },

  resetHeaderLabel: function(){
    $('.exp-pt-header > label').each((i, el) => $(el).text(this.heads[i].label).css({"text-decoration": "none"}));
  },

  createHeader: function() {
    Cons.showLoader();
    this.tHead.empty();
    this.colgroup.empty();

    let tr = $('<tr class="colHeaders">');

    this.colgroup.append(`<col style="width: 40px">`, `<col style="width: 40px">`);
    let th = $('<th class="ui-resizable">');
    let checkbox = $('<input/>')
      .addClass('uk-checkbox')
      .attr('type', 'checkbox')
      .on('change', e => {
        this.tBody.find('td > [type="checkbox"]').each((k, x) => {
          x.checked = !!e.target.checked;
        });
        this.tBody.find('td > [type="checkbox"]').each((k, x) => {
          $(x).trigger('change');
        });
      });
    th.append(checkbox);
    tr.append('<th>', th);

    let me = this;
    this.heads.forEach(item => {
      this.colgroup.append(`<col>`);
      let tmp_th = $('<th class="exp-pt-header ui-resizable">');
      let tmp_label = $('<label class="columnLabel">').text(item.label);
      let tmp_imput = $('<input type="text" class="uk-input">').css({'height': 'auto'}).hide();

      tmp_th.append(tmp_label).append(tmp_imput)
      .append(`<div class="resizeHelper ui-resizable-handle ui-resizable-e">&nbsp;</div>`);
      tr.append(tmp_th);

      let timeoutId;
      tmp_label.on("click", function (e) {
        timeoutId = setTimeout(() => {
          if(!timeoutId) return;
          me.tHead.find("th").not(tmp_th).find('label').removeClass("exp-pt-sorted-asc exp-pt-sorted-desc");
          if (tmp_label.hasClass("exp-pt-sorted-asc") || tmp_label.hasClass("exp-pt-sorted-desc")) {
            tmp_label.toggleClass("exp-pt-sorted-asc exp-pt-sorted-desc");
          } else {
            tmp_label.addClass("exp-pt-sorted-asc");
          }
          me.sortCmpID = item.columnID;
          me.sortDesc = tmp_label.hasClass("exp-pt-sorted-asc") ? false : true;
          me.createBody();
        }, 200);
      });

      tmp_label.on('dblclick', e => {
        clearTimeout(timeoutId);
        timeoutId = null;
        e.preventDefault();
        tmp_imput.show();
        tmp_label.hide();
        tmp_imput.on('blur', () => {
          tmp_label.show();
          tmp_imput.hide();
        });
        tmp_imput.on('keydown', e => {
          if(e.which === 13) {
            let inputVal = tmp_imput.val();
            this.resetHeaderLabel();
            if(inputVal && inputVal !== '') {
              tmp_label.text(inputVal).css({"text-decoration": "underline"});
              this.searchField = item.columnID;
              this.searchValue = inputVal;
            } else {
              tmp_label.text(item.label).css({"text-decoration": "none"});
              this.searchField = null;
              this.searchValue = null;
            }
            this.createBody();
            tmp_label.show();
            tmp_imput.hide();
            tmp_imput.off();
          }
        });
        tmp_imput.focus();
      });

    });
    setTimeout(() => {
      this.tHead.empty().append(tr);
      this.createBody();
      setTimeout(() => {
        this.registryTable.resizableColumns();
        Cons.hideLoader();
      }, 500);
    }, 100);
  },

  createMenuActions: function(massActions){
    const {containerID, items} = massActions;
    const menuContainer = $('<div uk-dropdown="mode: click">');
    const nav = $('<ul>', {class: 'uk-nav uk-dropdown-nav'});

    menuContainer.append(nav);
    $(`#${containerID}`).append(menuContainer);

    items.forEach(item => {
      const {name, handler, className = ''} = item;
      const navItem = $(`<li class="action-menu-item uk-disabled ${className}"><a href="#">${name}</a></li>`);
      nav.append(navItem);
      navItem.on('click', e => {
        handler(this.selectedItems, () => {
          this.createBody();
        });
      });
    });

  },

  reset: function(){
    this.filterRights = [];
    this.allRights = [];
    this.filterName = null;
    this.filterCode = null;
    this.filterID = null;
    this.sortCmpID = null;
    this.sortDesc = false;
    this.searchField = null;
    this.searchValue = null;
    this.filterSearchUrl = null;
    this.selectedItems = [];
    this.sum = null;

    this.registryTable = $('<table class="exp-table uk-table uk-table-small uk-table-divider uk-table-responsive">');
    this.colgroup = $('<colgroup>');
    this.tHead = $('<thead>');
    this.tBody = $('<tbody>');
    this.registryTable.append(this.colgroup).append(this.tHead).append(this.tBody);
    tableContainer.empty().append(this.registryTable);
  },

  calcSum: function(){
    if(!this.sum) return;

    const {formField, resultLabel} = this.sum;

    let url = `api/registry/count_data?registryCode=${this.registryCode}`;
    if(this.filterCode) url+=`&filterCode=${this.filterCode}`;
    if(this.searchString) url += `&searchString=${this.searchString}`;
    if(this.filterSearchUrl) {
      url += this.filterSearchUrl;
      if(this.searchField && this.searchValue) {
        let next = this.getNextFieldNumber(this.filterSearchUrl);
        url+=`&field${next}=${this.searchField}&condition${next}=CONTAINS&value${next}=${this.searchValue}`;
      }
    } else {
      if(this.searchField && this.searchValue) url+=`&field=${this.searchField}&condition=CONTAINS&value=${this.searchValue}`;
    }
    if(formField && resultLabel) {
      url += `&fieldCode=${formField}&countType=sum`;

      rest.synergyGet(url, data => {
        const {numericinput_sum_0} = data;
        if(numericinput_sum_0) {
          fire({type: 'change_label', text: localizedText(numericinput_sum_0, numericinput_sum_0, numericinput_sum_0, numericinput_sum_0)}, resultLabel);
        }
      });
    }
  },

  updateRigths: function(){
    if(this.filterCode) {
      const selectFilter = this.registryFilters.find(x => x.code == this.filterCode);
      if(selectFilter) {
        this.allRights = [...selectFilter.rights];
      } else {
        this.allRights = [];
      }
    } else {
      this.allRights = [...this.registryRights];
    }
  },

  init: async function(params){
    try {
      this.reset();
      const registryList = await getRegistryList();
      const info = await appAPI.getRegistryInfo(params.registryCode);

      if(!info || (info.hasOwnProperty('rights') && info.rights == "no")) throw new Error(`Нет прав на просмотр данного реестра`);

      this.registryInfo = info;
      this.heads = info.columns.filter(item => item.visible != '0')
      .sort((a, b) => {
        if (a.order == 0) return 0;
        return a.order - b.order;
      })
      .map(item => {
        return {label: item.label, columnID: item.columnID}
      });

      this.registryID = info.registryID;
      this.registryName = info.name;
      this.registryCode = params.registryCode;
      this.registryRights = registryList.find(x => x.registryCode == this.registryCode).rights;
      this.registryFilters = await appAPI.getRegistryFilters(this.registryCode);
      this.formCode = info.formCode;

      if(this.registryFilters && this.registryFilters.hasOwnProperty('errorCode') && this.registryFilters.errorCode != 0) throw new Error(this.registryFilters.errorMessage);

      if(params.filterCode) this.filterCode = params.filterCode;
      if(params.searchString) this.searchString = params.searchString;

      if(params.massActions) this.createMenuActions(params.massActions);

      if(params.hasOwnProperty('sum') && params.sum) {
        this.sum = params.sum;
        fire({type: 'change_label', text: localizedText('0', '0', '0', '0')}, this.sum.resultLabel);
      }

      this.updateRigths();
      if(!this.allRights.includes("rr_list")) throw new Error(`Нет прав на просмотр данного реестра`);

      this.createHeader();
      Paginator.init();
    } catch (err) {
      Cons.hideLoader();
      console.log('ERROR init registry list', err);
      showMessage(err.message, 'error');
    }
  }
}

compContainer.off()
.on('renderNewTable', e => {
  if(!e.hasOwnProperty('eventParam')) return;
  registryTable.init(e.eventParam);
})
.on('updateTableBody', e => {
  if(!registryTable.registryCode) return;
  if(Paginator.currentPage != 1) return;
  if(e.hasOwnProperty('eventParam')) {
    const {filterCode = null, filterSearchUrl = null} = e.eventParam;
    if(filterCode) registryTable.filterCode = filterCode;
    if(filterSearchUrl) registryTable.filterSearchUrl = filterSearchUrl;
  }
  Paginator.currentPage = 1;
  registryTable.createBody();
})
.on('searchInRegistry', e => {
  if(!e.hasOwnProperty('eventParam')) return;
  const {searchString = null} = e.eventParam;
  registryTable.searchString = searchString;
  Paginator.currentPage = 1;
  registryTable.createBody();
})
.on('filterRegistryRows', e => {
  if(!e.hasOwnProperty('eventParam')) return;
  const {filterSearchUrl = null} = e.eventParam;
  registryTable.filterSearchUrl = filterSearchUrl;
  Paginator.currentPage = 1;
  registryTable.createBody();
}).on('getXLS', e => {

  Cons.showLoader();

  let url = registryTable.getUrl(true);
  url += `&pageNumber=1&countInPart=1&loadData=false`;

  rest.synergyGet(url, part => {
    Cons.hideLoader();

    UIkit.modal.confirm(`Вы собираетесь выгрузить ${part.count} записей. Продолжить?`,
      {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}})
    .then(() => {

      if(registryTable.searchString || registryTable.filterSearchUrl || registryTable.searchField) {
        Cons.showLoader();
        rest.synergyGet(registryTable.getUrl(true), data => {
          let excelData = [];
          data.result.forEach(res => {
            let tmpValues = {};
            registryTable.heads.forEach(col => tmpValues[col.label] = res.fieldValue[col.columnID] || "");
            excelData.push(tmpValues);
          });

          try {
            let opts = {headers: true, column: {style:{Font:{Bold:"1"}}}};
            let result = alasql(`SELECT * INTO XLS("${registryTable.registryName}_${formatDate()}.xls",?) FROM ?`, [opts, excelData]);
            Cons.hideLoader();
          } catch (e) {
            console.log(e.message);
            Cons.hideLoader();
            showMessage(i18n.tr('Произошла ошибка при выгрузке записей реестра'), 'error');
          }
        });
      } else {
        getSystemReport();
      }

    }, () => null);
  });
});

$(document).off()
.on('contextmenu', () => $('.exp-context-menu').remove())
.on('click', () => $('.exp-context-menu').remove());
