/*
					Object Type - задается битовой маской
					Объект конфигуратора - 0
					Тип объекта цель - 2
					Тип объекта поручение - 4
					Тип объекта мероприятие (план) - 64
					Тип объекта Задача - 8
					Тип объекта показатель - 16
					Пользователь - 32
					План - 256
					Портфель проектов - 128
					Документ в журнале документов - 1024
					Процесс - 512
					Департамент - 2048
					Должность - 4096
					Маршрут - 8192
					Карта - 16384
					Файл - 32768
					Реестр - 65536
					Карточка документа - 131072
					Группа - 262144
*/

const objectTypes = [0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144];

this.ReportComponent = class {
  constructor(params) {
    this.objectType = params?.objectType || null;
    this.selectorContainer = params?.selectorContainer || null;
    this.registryCode = params?.registryCode || null;
    this.registryListComponent = params?.registryListComponent || null;
    this.reportList = null;
    this.reportURL = null;
    this.reportName = null;
    this.listValues = {};
    this.uploadDataHandler = params?.uploadDataHandler || null;

    this.init();
  }

  reportDownload() {
    Cons.showLoader();
    try {
      let me = this;
      let xhr = new XMLHttpRequest();
      xhr.open('POST', me.reportURL, true);
      xhr.setRequestHeader("Authorization", "Basic " + btoa(unescape(encodeURIComponent(Cons.creds.login + ":" + Cons.creds.password))));
      xhr.responseType = 'arraybuffer';
      xhr.onload = function () {
        if (this.status === 200) {
          let type = xhr.getResponseHeader('Content-Type');
          let blob = new Blob([this.response], {type: type});
          if (typeof window.navigator.msSaveBlob !== 'undefined') {
            window.navigator.msSaveBlob(blob, me.reportName);
          } else {
            let URL = window.URL || window.webkitURL;
            let downloadUrl = URL.createObjectURL(blob);
            if (me.reportName) {
              let a = document.createElement("a");
              if (typeof a.download === 'undefined') {
                window.location = downloadUrl;
              } else {
                a.href = downloadUrl;
                a.download = me.reportName;
                document.body.appendChild(a);
                a.click();
              }
            } else {
              window.location = downloadUrl;
            }
            setTimeout(function () {
              URL.revokeObjectURL(downloadUrl);
            }, 100);
          }
          Cons.hideLoader();
        } else {
          Cons.hideLoader();
          console.log(this.status, this);
          showMessage(i18n.tr('Произошла ошибка при формировании отчета'),'error');
        }
      };
      xhr.send();
    } catch (e) {
      console.log(e);
      Cons.hideLoader();
      showMessage(i18n.tr('Произошла ошибка при формировании отчета'),'error');
    }
  }

  getReportName(report) {
    const t = {
      ru: report.nameru,
      kk: report.namekz,
      en: report.nameen
    }
    return t[AS.OPTIONS.locale];
  }

  getParamRow(param) {
    const paramRow = $('<div class="uk-margin-small">');
    const label = $(`<label class="uk-form-label fonts" for="${param.code}">${i18n.tr(param.label)}</label>`);
    const controls = $('<div class="uk-form-controls">');

    switch (param.type) {

      case "java.util.Date": {
        const inputDate = $(`<input class="uk-input fonts" id="${param.code}" type="date">`);
        inputDate.val(new Date().toISOString().substring(0, 10));
        controls.append(inputDate);
        break;
      }

      case "java.util.List": {
        const p = param.code.split('.');
        const dictCode = p[0];
        const dictValue = p[1];
        const dictKey = p[2].split('_')[0];

        const scrollable = $(`<div id="${param.code}" class="uk-panel uk-panel-scrollable">`);
        const ul = $('<ul class="uk-list">');

        scrollable.append(ul);
        controls.append(scrollable);

        this.listValues[param.code] = [];
        rest.synergyGet(`api/dictionaries/${dictCode}`, dict => {
          let items = [];
          for (const key in dict.items) {
            items.push({value: dict.items[key][dictValue].value, key: dict.items[key][dictKey].value});
          }

          items = items.sort((a, b) => {
            a = a.value.toUpperCase();
            b = b.value.toUpperCase();
            if (a > b) return 1;
            if (a < b) return -1;
            return 0;
          });

          items.forEach(item => {
            const li = $('<li>');
            const checkbox = $('<input/>').addClass('uk-checkbox').attr('type', 'checkbox');
            const label = $('<label>', {class: 'fonts dict-menu-item'});
            label.append(checkbox, `<span> ${item.value}</span>`);

            checkbox.on('change', e => {
              if(e.target.checked) {
                if(this.listValues[param.code].indexOf(item.key) === -1)
                this.listValues[param.code].push(item.key);
              } else {
                const index = this.listValues[param.code].indexOf(item.key);
                if(index !== -1) this.listValues[param.code].splice(index, 1);
              }
            });

            ul.append(li.append(label));
          });
        });
        break;
      }

      default: {
        if(param.code.substr(0, 8) == 'registry') {
          const paramRegCode = param.code.split('.')[1];
          const buttonReg = $('<a class="uk-form-icon uk-form-icon-flip" href="#" uk-icon="icon: more"></a>');
          const inputReg = $(`<input id="${param.code}" class="uk-input" type="text" style="background-color: #fff; color: #666;" disabled>`);
          let selectDocId = null;

          buttonReg.on('click', e => {
            e.preventDefault();
            e.target.blur();
            e.stopPropagation();

            Cons.showLoader();
            AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/registry/info?locale=${AS.OPTIONS.locale}&code=${paramRegCode}`, registryInfo => {
              if(!registryInfo.hasOwnProperty('registryCustomFilters')) registryInfo.registryCustomFilters = [];
              Cons.hideLoader();
              AS.SERVICES.showRegistryLinkDialog(registryInfo, false, selectDocId, documentId => {
                selectDocId = [documentId];
                AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/formPlayer/getDocMeaningContent?documentId=${documentId}`, content => {
                  inputReg.val(content).attr('documentId', documentId);
                }, 'text');
              });
            });
          });
          controls.append($('<div class="uk-inline uk-width-1-1">').append(buttonReg).append(inputReg));
        } else if (param.code.substr(-11) == '_dictionary') {

          const p = param.code.split('.');
          const dictCode = p[0];
          const dictKey = p[1];
          const dictValue = p[2].split('_')[0];

          const select = $(`<select>`, {class: 'uk-select', id: param.code});
          controls.append(select);

          this.listValues[param.code] = [];
          rest.synergyGet(`api/dictionaries/${dictCode}`, dict => {
            let items = [];
            for (const key in dict.items) {
              items.push({value: dict.items[key][dictValue].value, key: dict.items[key][dictKey].value});
            }

            items = items.sort((a, b) => {
              a = a.value.toUpperCase();
              b = b.value.toUpperCase();
              if (a > b) return 1;
              if (a < b) return -1;
              return 0;
            });

            items.forEach(item => select.append(`<option value="${item.key}" title="${item.value}">${item.value}</option>`));
          });

        } else {
          switch (param.code) {
            case "departments_id":
            case "department_id":
              let multiSelDep = param.code == 'departments_id' ? true : false;
              let selectDep = null;
              let button = $('<a class="uk-form-icon uk-form-icon-flip" href="#" uk-icon="icon: more"></a>');
              let input = $(`<input id="${param.code}" class="uk-input" type="text" style="background-color: #fff; color: #666;" disabled>`);

              button.on('click', e => {
                e.preventDefault();
                e.target.blur();
                e.stopPropagation();

                AS.SERVICES.showDepartmentChooserDialog(selectDep, multiSelDep, null, null, null, null, AS.OPTIONS.locale, departments => {
                  selectDep = departments;
                  let depIDs = departments.map(x => x.departmentId).join(',');
                  let depNames = departments.map(x => x.departmentName).join('; ');
                  input.val(depNames).attr('title', depNames).attr('dep-ids', depIDs);
                });
              });
              controls.append($('<div class="uk-inline uk-width-1-1">').append(button).append(input));
              break;

            case "users_id":
            case "user_id":
              let multiSelUser = param.code == 'users_id' ? true : false;
              let selectUsers = null;
              let buttonUsers = $('<a class="uk-form-icon uk-form-icon-flip" href="#" uk-icon="icon: more"></a>');
              let inputUsers = $(`<input id="${param.code}" class="uk-input" type="text" style="background-color: #fff; color: #666;" disabled>`);

              buttonUsers.on('click', e => {
                e.preventDefault();
                e.target.blur();
                e.stopPropagation();

                AS.SERVICES.showUserChooserDialog(selectUsers, multiSelUser, null, null, null, null, AS.OPTIONS.locale, users => {
                  selectUsers = users;
                  let userIDs = users.map(x => x.personID).join(',');
                  let userNames = users.map(x => x.personName).join('; ');
                  inputUsers.val(userNames).attr('title', userNames).attr('user-ids', userIDs);
                });
              });
              controls.append($('<div class="uk-inline uk-width-1-1">').append(buttonUsers).append(inputUsers));
              break;

            case "currentuser_id": break;

            default:
              controls.append(`<input class="uk-input fonts" id="${param.code}" type="text" placeholder="${param.label}">`);
          }
        }
      }
    }

    paramRow.append(label).append(controls);
    return paramRow;
  }

  getReport(report){
    this.reportURL = `${window.location.origin}/Synergy/rest/api/report/do?reportID=${report.reportID}`;
    this.reportName = report.defaultName;

    if(report.params && report.params.length > 0) {
      let dialog = $('<div uk-modal>');
      let md = $('<div>', {class: 'uk-modal-dialog'});
      let modalBody = $('<div class="uk-modal-body" uk-overflow-auto>');
      let footer = $('<div class="uk-modal-footer uk-text-right">')
      let button = $(`<button class="uk-button uk-button-primary" type="button">${i18n.tr("Готово")}</button>`);
      dialog.append(md);
      footer.append(`<button class="uk-button uk-button-default uk-modal-close uk-margin-right" type="button">${i18n.tr("Отмена")}</button>`);
      footer.append(button);
      md.append(`<div class="uk-modal-header"><h3>${this.getReportName(report)}</h3></div>`).append(modalBody).append(footer);

      report.params.forEach(param => modalBody.append(this.getParamRow(param)));

      UIkit.modal(dialog).show();
      dialog.on('hidden', () => dialog.remove());

      button.on('click', () => {
        report.params.forEach(param => {
          let val = "";
          switch (param.type) {
            case "java.util.Date":
              val = $(`[id="${param.code}"]`).val();
              let time = " 00:00:00";
              if(!val) val = new Date().toISOString().substring(0, 10);
              if(param.code == "start") time = " 00:00:00";
              if(param.code == "stop") time = " 23:59:59";
              val += time;
              break;
            case "java.util.List": val = this.listValues[param.code].join(','); break;
            default:
              if(param.code.substr(0, 8) == 'registry') {
                val = $(`[id="${param.code}"]`).attr('documentId');
              } else if (param.code.substr(-11) == '_dictionary') {
                val = $(`[id="${param.code}"]`).val() || "";
              } else {
                switch (param.code) {
                  case "department_id":
                  case "departments_id":
                    val = $(`[id="${param.code}"]`).attr('dep-ids') || "";
                    break;
                  case "user_id":
                  case "users_id":
                    val = $(`[id="${param.code}"]`).attr('user-ids') || "";
                    break;
                  case "currentuser_id": val = AS.OPTIONS.currentUser.userid; break;
                  default:
                    val = $(`[id="${param.code}"]`).val() || "";
                }
              }
          }
          this.reportURL += `&${param.code}=${val}`;
        });
        this.reportDownload();
        UIkit.modal(dialog).hide();
      });
    } else {
      this.reportDownload();
    }
  }

  createReportMenu() {
    if(this.uploadDataHandler && typeof this.uploadDataHandler === 'function') {
      const getXls = $('<a>');
      getXls.text(i18n.tr("Выгрузить в Excel"));

      getXls.on('click', e => {
      	e.preventDefault();
        this.uploadDataHandler();
      });

      this.reportsMenu.append($(`<li>`).append(getXls));

      if(this.reportList && this.reportList.length) this.reportsMenu.append('<li class="uk-nav-divider"></li>');

    }

    if(this.reportList && this.reportList.length) {
      this.reportList.forEach(report => {
        const item = $(`<li><a href="#">${this.getReportName(report)}</a></li>`);
        item.on('click', e => this.getReport(report));
        this.reportsMenu.append(item);
      });
    }
  }

  renderHTML(){
  	const container = $('<div>', {class: 'uk-flex-inline uk-flex-wrap uk-flex-left'});
  	const printButton =  $('<button>', {id: 'button-print-report', class: 'uk-button uk-button-default'});
  	const menuContainer = $('<div>', {class: 'report-menu', 'uk-dropdown': 'mode: click'});
  	this.reportsMenu = $('<ul>', {class: 'uk-nav uk-dropdown-nav'});

  	menuContainer.append(this.reportsMenu);
  	printButton.append(`<span uk-icon="print"></span>`);  	
  	container.append(printButton, menuContainer);
  	this.componentContainer.append(container);
  }

  checkObjectTypeMatch() {
    if (!this.objectType) return false;
    this.objectType = Array.isArray(this.objectType) ? this.objectType : [this.objectType];
    return this.objectType.some(t => objectTypes.includes(Number(t)));
  }

  init() {
  	try {
  		if(!this.selectorContainer) throw new Error('Не передан селектор контейнера для отрисовки кнопки');

  		this.componentContainer = $(this.selectorContainer);

  		if(!this.componentContainer || !this.componentContainer.length) throw new Error('Не передан или передан некорректный селектор контейнера');

      if(!this.checkObjectTypeMatch()) throw new Error(`ERROR ReportComponent: objectType not supported [objectType: ${this.objectType}]`);

  		this.renderHTML();

  		rest.synergyGet('api/report/list', res => {
        this.reportList = res.filter(x => {
          const typeMatch = this.objectType.includes(x.objectType);

          if (this.registryCode) {
            return typeMatch && x.objectCode == this.registryCode;
          } else {
            return typeMatch;
          }
        });

  			this.createReportMenu();
  		});

  	} catch (err) {
  		console.log(err.message);
  	}
  }
};
