const getInputDateTime = (d, t) => $(`<input type="date" class="uk-input" style="max-width: 140px;" value="${d || ''}"><input type="time" class="uk-input" style="max-width: 100px;" value="${t || ''}">`);

const createDateTimeInput = date => {
  if(date) date = date.split(' ');
  const container = $('<div>', {class: 'resolution_datetime_input_container'});
  const dateTimeInput = date ? getInputDateTime(date[0], date[1]) : getInputDateTime();
  container.append(dateTimeInput);
  return {container, dateTimeInput};
}

const createSelectComponent = (items, multiple = false) => {
  const container = $('<div>', {class: 'uk-form-controls'});
  const select = $('<select class="uk-select" style="min-width: 100px;">');

  if(multiple) select.attr('multiple', 'multiple');
  if(items) items.sort((a,b) => a.value - b.value)
  .forEach(item => select.append(`<option value="${item.value}" title="${item.label}">${item.label}</option>`));

  container.append(select);

  return {container, select};
}

const createUserParamBlock = (labelUsers, placeholder, type, item, multiSelectable = false, filterDepartmentID = null) => {
  const container = $('<div>', {class: 'uk-inline uk-width-expand', style: "min-width: 170px;"});
  const button = $('<a class="uk-form-icon uk-form-icon-flip" href="javascript:void(0);" uk-icon="icon: users"></a>');
  const input = $(`<input class="uk-input" type="text" style="background: #fff;" placeholder="${placeholder}" disabled>`);

  let values = null;
  if(type == 'responsible') {
    if(item.userID) values = [{personName: item.user, personID: item.userID}];
  } else if (type == 'users') {
    values = item.users.map(x => ({personID: x.userID, personName: x.user}));
  }

  container.append(button, input);

  if(values) {
    let userNames = values.map(x => x.personName).join('; ');
    input.val(userNames).attr('title', userNames);
    labelUsers.text(`${placeholder}: ${userNames}`);
  } else {
    labelUsers.text(`${placeholder}:`);
  }

  button.on('click', e => {
    //(values, multiSelectable, isGroupSelectable, showWithoutPosition, filterPositionID, filterDepartmentID, locale, handler)
    AS.SERVICES.showUserChooserDialog(values, multiSelectable, false, false, null, filterDepartmentID, AS.OPTIONS.locale, users => {
      let userNames = users.map(x => x.personName).join('; ');
      input.val(userNames).attr('title', userNames);
      labelUsers.text(`${placeholder}: ${userNames}`);
      if(type == 'responsible') {
        item.user = users[0].personName;
        item.userID = users[0].personID;
      } else if (type == 'users') {
        item.users = users.map(x => ({userID: x.personID, user: x.personName}));
      }
      values = users;
    });
  });

  return {container, button, input};
}

this.Resolution = class {
  constructor(_doc) {
    this._doc = _doc;
    this.itemID = 0;
    this.items = {};
    this.actionID = null;
    this.documentID = null;

    this.init();
  }

  getModal() {
    const dialog = $('<div class="uk-flex-top" uk-modal="bg-close: false; esc-close: false;">');
    const md = $('<div>', {class: 'uk-modal-dialog uk-margin-auto-vertical', style: 'width: 900px; height: 500px;'});
    const modalBody = $('<div>', {class: 'uk-modal-body resolution_body'});
    const footer = $('<div>', {class: 'uk-modal-footer resolution_footer'});
    const panelActions = $('<div>', {class: 'resolution_panel_actions'});
    this.panelItems = $('<div>', {class: 'resolution_panel_items'});

    this.buttonAddResolutionItem = $(`<button class="uk-button uk-button-default uk-button-small" type="button">${i18n.tr("Добавить пункт")}</button>`);
    this.buttonPassResolution = $(`<button class="uk-button uk-button-primary uk-button-small" type="button">${i18n.tr("Принять")}</button>`);
    this.buttonSaveResolution = $(`<button class="uk-button uk-button-default uk-button-small" type="button">${i18n.tr("Сохранить")}</button>`);
    this.isControl = $(`<input class="uk-checkbox" type="checkbox" id="resolution_is_control">`);

    if(this.resolution.controlled) this.isControl.prop('checked', true);

    modalBody.append(panelActions, this.panelItems);

    panelActions.append(
      this.buttonAddResolutionItem,
      $('<label>', {class: "uk-text-small"}).append(this.isControl, ` ${i18n.tr('Является контрольным')}`)
    );

    footer.append(this.buttonPassResolution);
    if(this.resolution.statusID == 0) footer.append(this.buttonSaveResolution);

    md.append(`<button class="uk-modal-close-default modal-close-custom" type="button" uk-close></button>`,
    `<div class="uk-modal-header"><h3>${i18n.tr("Резолюция")}</h3></div>`, modalBody, footer);
    dialog.append(md);

    return dialog;
  }

  getTmpItem(){
    return {
      name: null,
      userID: null,
      user: null,
      users: [],
      finishdate: {
        date: null
      },
      typeID: null,
      completionFormID: null,
      completionFormCode: null,
      itemID: null,
      dict_id: null,
      item_name: null
    }
  }

  addResolutionItem(item){
    const itemBlock = $('<div>', {class: 'resolution_item active'});
    const panel1 = $('<div>');
    const panel2 = $('<div>');
    const deleteButton = $(`<a href="javascript:void(0)" uk-icon="trash"></a>`);

    const itemNameBlock = $('<div>', {class: 'resolution_item_name'});
    const labelName = $('<span>', {class: 'resolution_item_name_label uk-text-normal'});
    const inputName = $('<input>', {class: "uk-input", type: "text", placeholder: i18n.tr("Введите формулировку пункта резолюции")});
    const datalist = $('<datalist>');

    let tmpItemID = `item-${this.itemID}`;

    if(item) {
      tmpItemID = item.itemID;
      inputName.val(item.name);
      labelName.text(item.name);
    } else {
      const tmpItem = this.getTmpItem();
      tmpItem.dict_id = this.workTypes[0].dict_id;
      tmpItem.item_name = this.workTypes[0].item_name;
      tmpItem.typeID = 3;

      this.items[tmpItemID] = tmpItem;
      this.itemID++;
    }

    inputName.attr('list', tmpItemID);
    datalist.attr('id', tmpItemID);

    const itemParamBlock = $('<div>', {class: 'resolution_item_param'});

    const responsibleCheck = $(`<input class="uk-checkbox" type="checkbox">`);
    const labelUser = $('<span>', {class: 'resolution_item_users_label uk-text-small uk-text-bold'});
    const {container: userContainer, button: userButton, input: userInput} = createUserParamBlock(labelUser, i18n.tr("Ответственный"), 'responsible', this.items[tmpItemID]);

    const {container: workFinishContainer, dateTimeInput} = createDateTimeInput();
    const labelFinishDate = $('<span>', {class: 'resolution_item_finishdate_label uk-text-small uk-text-bold'});

    const wtList = this.workTypes.map(x => ({label: x.item_name, value: x.dict_id}));
    const {container: workTypeContainer, select: workTypeSelect} = createSelectComponent(wtList);
    const labelWT = $('<span>', {class: 'resolution_item_work_type_label uk-text-small uk-text-bold'});

    const cfList = this.completionForms.map(x => ({label: x.name, value: x.id}));
    cfList.unshift({label: i18n.tr('Результат работы'), value: 'empty'});
    const {container: cfContainer, select: cfSelect} = createSelectComponent(cfList);
    const labelCF= $('<span>', {class: 'resolution_item_cf_label uk-text-small uk-text-bold'});

    const itemUsersBlock = $('<div>', {class: 'resolution_item_users'});
    const labelUsers = $('<span>', {class: 'resolution_item_users_label uk-text-small uk-text-bold'});
    const {container: usersContainer} = createUserParamBlock(labelUsers, i18n.tr("Исполнители"), 'users', this.items[tmpItemID], true);

    if(this.items[tmpItemID].finishdate.date) {
      let finishDate = new Date(Number(this.items[tmpItemID].finishdate.date));
      finishDate = AS.FORMS.DateUtils.formatDate(finishDate, AS.FORMS.DateUtils.DATE_FORMAT_FULL);
      finishDate = finishDate.split(' ');
      $(dateTimeInput[0]).val(finishDate[0]);
      $(dateTimeInput[1]).val(finishDate[1].slice(0,5));
    } else if(this.completion_date_for_resolution) {
      //Подставлять дату завершения документа в пункты резолюции
      let finishDate = this.resolution.maxFinishDate.split(' ');
      $(dateTimeInput[0]).val(finishDate[0]);
      $(dateTimeInput[1]).val(finishDate[1].slice(0,5));
      this.items[tmpItemID].finishdate.date = String(new Date(this.resolution.maxFinishDate).getTime());
    }

    const wtItem = this.workTypes.find(x => x.dict_id == this.items[tmpItemID].dict_id);
    const cfItem = this.completionForms.find(x => x.id == this.items[tmpItemID].completionFormID);

    if(this.items[tmpItemID].dict_id) {
      workTypeSelect.val(this.items[tmpItemID].dict_id);
    } else {
      workTypeSelect.val(wtList[0].value);
    }
    if(this.items[tmpItemID].completionFormID) cfSelect.val(this.items[tmpItemID].completionFormID);

    labelFinishDate.text(`${i18n.tr("Завершение")}: ${$(dateTimeInput[0]).val()} ${$(dateTimeInput[1]).val()}`);
    if(wtItem) {
      labelWT.text(`${i18n.tr("Тип")}: ${wtList.find(x => x.value == this.items[tmpItemID].dict_id).label}`);
    } else {
      labelWT.text(`${i18n.tr("Тип")}:`);
    }
    if(cfItem) {
      labelCF.text(`${i18n.tr("Форма завершения")}: ${cfList.find(x => x.value == this.items[tmpItemID].completionFormID).label}`);
    } else {
      labelCF.text(`${i18n.tr("Форма завершения")}:`);
    }

    this.resolutionText.forEach(x => datalist.append(`<option value="${x.text}"></option>`));

    this.panelItems.find('.resolution_item').removeClass('active');

    itemNameBlock.append(inputName, datalist, labelName);
    itemParamBlock.append(responsibleCheck, userContainer, labelUser, workFinishContainer, labelFinishDate, workTypeContainer, labelWT, cfContainer, labelCF);
    itemUsersBlock.append(usersContainer, labelUsers);
    panel1.append(itemNameBlock, itemParamBlock, itemUsersBlock);
    panel2.append(deleteButton);
    itemBlock.append(panel1, panel2);
    this.panelItems.append(itemBlock);

    if(item) {
      responsibleCheck.prop('disabled', true);
      workTypeSelect.prop('disabled', true);
      userButton.attr('disabled', true);
      if(item.userID) responsibleCheck.prop('checked', true);
    } else {
      responsibleCheck.prop('checked', true);
    }

    responsibleCheck.on('change', e => {
      if(e.target.checked) {
        userButton.attr('disabled', false);
      } else {
        userButton.attr('disabled', true);
        labelUser.text(`${i18n.tr("Ответственный")}:`);
        this.items[tmpItemID].userID = null;
        this.items[tmpItemID].user = '';
        userInput.val(null);
      }
    });

    $(dateTimeInput[0]).on('change', e => {
      let datetime = '';
      if($(dateTimeInput[0]).val() != '') {
        datetime = $(dateTimeInput[0]).val();
        if($(dateTimeInput[1]).val() != '') {
          datetime += ` ${$(dateTimeInput[1]).val()}`;
        } else {
          $(dateTimeInput[1]).val(this.day_finish_time);
          datetime += ` ${this.day_finish_time}`;
        }
      }
      labelFinishDate.text(`${i18n.tr("Завершение")}: ${datetime}`);
      this.items[tmpItemID].finishdate.date = String(new Date(datetime).getTime());
    });
    $(dateTimeInput[1]).on('change', e => {
      let datetime = '';
      if($(dateTimeInput[0]).val() != '') {
        datetime = $(dateTimeInput[0]).val();
        if($(dateTimeInput[1]).val() != '') {
          datetime += ` ${$(dateTimeInput[1]).val()}`;
        } else {
          datetime += ` ${this.day_finish_time}`;
        }
      }
      labelFinishDate.text(`${i18n.tr("Завершение")}: ${datetime}`);
      this.items[tmpItemID].finishdate.date = String(new Date(datetime).getTime());
    });

    workTypeSelect.on('change', e => {
      const changeFields = () => {
        // блокируем фз и юзера
        cfSelect.prop('disabled', true).val('empty');
        this.items[tmpItemID].completionFormCode = null;
        this.items[tmpItemID].completionFormID = null;
        labelCF.text(`${i18n.tr("Форма завершения")}:`);

        userButton.attr('disabled', true);
        labelUser.text(`${i18n.tr("Ответственный")}:`);
        this.items[tmpItemID].userID = null;
        this.items[tmpItemID].user = '';
        userInput.val(null);
        responsibleCheck.prop('disabled', true).prop('checked', false);

        $(dateTimeInput[0]).attr('disabled', false);
        $(dateTimeInput[1]).attr('disabled', false);
      }

      const wtItem = this.workTypes.find(x => x.dict_id == workTypeSelect.val());
      this.items[tmpItemID].dict_id = wtItem.dict_id;
      this.items[tmpItemID].item_name = wtItem.item_name;
      labelWT.text(`${i18n.tr("Тип")}: ${wtItem.item_name}`);

      switch (wtItem.item_number) {
        case 1: { //работа
          // все открываем
          responsibleCheck.prop('disabled', false);
          cfSelect.prop('disabled', false);
          $(dateTimeInput[0]).attr('disabled', false);
          $(dateTimeInput[1]).attr('disabled', false);

          this.items[tmpItemID].typeID = 3;
          break;
        }
        case 2: {
          changeFields();
          this.items[tmpItemID].typeID = 0;
          break;
        }
        case 3: {
          changeFields();
          this.items[tmpItemID].typeID = 1;
          break;
        }
        case 4: {
          changeFields();
          this.items[tmpItemID].typeID = 2;
          break;
        }
        case 5: { // Резолюция
          // все открываем
          userButton.attr('disabled', false);
          responsibleCheck.prop('disabled', false).prop('checked', true);

          responsibleCheck.prop('disabled', false);
          cfSelect.prop('disabled', false);
          $(dateTimeInput[0]).attr('disabled', false);
          $(dateTimeInput[1]).attr('disabled', false);

          this.items[tmpItemID].typeID = 33;
          break;
        }
        case 6: { // Отправка документа
          // блокируем юзер, дата, фз
          cfSelect.prop('disabled', true).val('empty');
          this.items[tmpItemID].completionFormCode = null;
          this.items[tmpItemID].completionFormID = null;
          labelCF.text(`${i18n.tr("Форма завершения")}:`);

          userButton.attr('disabled', true);
          labelUser.text(`${i18n.tr("Ответственный")}:`);
          this.items[tmpItemID].userID = null;
          this.items[tmpItemID].user = '';
          userInput.val(null);
          responsibleCheck.prop('disabled', true).prop('checked', false);

          $(dateTimeInput[0]).attr('disabled', true).val(null);
          $(dateTimeInput[1]).attr('disabled', true).val(null);
          labelFinishDate.text(`${i18n.tr("Завершение")}:`);
          this.items[tmpItemID].finishdate.date = null;

          this.items[tmpItemID].typeID = 17;
          break;
        }
      }
    });

    cfSelect.on('change', e => {
      const cfItem = this.completionForms.find(x => x.id == cfSelect.val());
      if(cfItem) {
        this.items[tmpItemID].completionFormCode = cfItem.code;
        this.items[tmpItemID].completionFormID = cfItem.id;
        labelCF.text(`${i18n.tr("Форма завершения")}: ${cfItem.name}`);
      } else {
        this.items[tmpItemID].completionFormCode = null;
        this.items[tmpItemID].completionFormID = null;
        labelCF.text(`${i18n.tr("Форма завершения")}:`);
      }
    });

    inputName.on('change', e => {
      this.items[tmpItemID].name = inputName.val();
      labelName.text(this.items[tmpItemID].name);
    });

    itemBlock.on('click', e => {
      this.panelItems.find('.resolution_item').removeClass('active');
      itemBlock.addClass('active');
    });

    deleteButton.on('click', e => {
      e.preventDefault();
      itemBlock.remove();
      this.panelItems.find('.resolution_item').removeClass('active');
      this.panelItems.find('.resolution_item:first').addClass('active');
      delete this.items[tmpItemID];
      this.resolution.items = Object.values(this.items);
    });

    this.panelItems.scrollTop(this.panelItems.offset().top);
  }

  getParamURL(){
    this.resolution.items = Object.values(this.items);

    const params = new URLSearchParams();

    const data = this.resolution.items.map(x => ({
      name: x.name,
      userID: x.userID,
      usersID: x.users.map(u => u.userID),
      finishDate: x.finishdate.date,
      typeID: x.typeID,
      completionFormID: x.completionFormID,
      completionFormCode: x.completionFormCode,
      itemID: x.itemID,
      dict_id: x.dict_id
    }));

    if(this.resolution.projectID) params.append("projectID", this.resolution.projectID);
    if(this.actionID) params.append("workID", this.actionID);
    if(this.documentID) params.append("documentID", this.documentID);

    params.append("controlled", this.resolution.controlled);
    params.append("data", JSON.stringify(data));

    return params;
  }

  checkItemFinishDate(item){
    const { maxFinishDate } = this.resolution;
    const currDate = AS.FORMS.DateUtils.formatDate(new Date(), AS.FORMS.DateUtils.DATE_FORMAT_FULL);
    let itemFinishDate = item.finishdate.date;

    if(!itemFinishDate) return i18n.tr('Дата завершения некоторых элементов меньше текущей даты');

    itemFinishDate = new Date(Number(itemFinishDate));
    itemFinishDate = AS.FORMS.DateUtils.formatDate(itemFinishDate, AS.FORMS.DateUtils.DATE_FORMAT_FULL);

    if(itemFinishDate < currDate) return i18n.tr('Дата завершения некоторых элементов меньше текущей даты');

    if(!this.date_resolution_after_finish_document && itemFinishDate > maxFinishDate) return i18n.tr('Дата завершения каждого из пунктов резолюции не должна превышать срок документа');

    return null;
  }

  checkResolutionItems(){
    const result = {errorCode: 0, errorMessage: ''};
    const errors = new Set();

    for(const itemID in this.items) {
      const item = this.items[itemID];
      const wtItem = this.workTypes.find(x => x.dict_id == item.dict_id);
      const chDate = this.checkItemFinishDate(item);

      // проверить формулировку
      if(!item.name) {
        errors.add(i18n.tr('Не для всех элементов резолюции введены формулировки'));
        result.errorCode++;
      }

      switch (wtItem.item_number) {
        // проверить дату, ответсвтвенного (если стоит галочка) и исполнителей (если нет галочки ответственного)
        case 1: // работа
        case 5: { // Резолюция
          if(!item.userID && !item.users.length) {
            errors.add(i18n.tr('Не для всех элементов резолюции выбраны ответственные пользователи'));
            result.errorCode++;
          }
          if(chDate) {
            errors.add(chDate);
            result.errorCode++;
          }
          break;
        }
        // проверить исполнителей и дату
        case 2: // согласование
        case 3: // утверждение
        case 4: { // ознакомление
          if(!item.users.length) {
            errors.add(i18n.tr('Не для всех элементов резолюции выбраны ответственные пользователи'));
            result.errorCode++;
          }
          if(chDate) {
            errors.add(chDate);
            result.errorCode++;
          }
          break;
        }
        // проверить исполнителей
        case 6: { // Отправка документа
          if(!item.users.length) {
            errors.add(i18n.tr('Не для всех элементов резолюции выбраны ответственные пользователи'));
            result.errorCode++;
          }
          break;
        }
      }
    }

    if(result.errorCode != 0) result.errorMessage = [...errors].join('<br>');

    return result;
  }

  async passResolution(){
    Cons.showLoader();
    try {
      const itemsError = this.checkResolutionItems();

      if(itemsError.errorCode != 0) throw new Error(itemsError.errorMessage);

      const params = this.getParamURL();
      params.append("type", 'ACCEPT');

      const resultSave = await appAPI.resolution.save(params);
      if(resultSave.errorCode != 0) throw new Error(resultSave.errorMessage);

      Cons.hideLoader();
      showMessage(resultSave.errorMessage, 'success');
      UIkit.modal(this.dialog).hide();

    } catch (err) {
      UIkit.notification.closeAll();
      showMessage(i18n.tr(err.message), 'error');
      Cons.hideLoader();
    }
  }

  async saveResolution(){
    Cons.showLoader();
    try {
      const itemsError = this.checkResolutionItems();

      if(itemsError.errorCode != 0) throw new Error(itemsError.errorMessage);

      const params = this.getParamURL();
      params.append("type", 'SAVE');

      const resultSave = await appAPI.resolution.save(params);
      if(resultSave.errorCode != 0) throw new Error(resultSave.errorMessage);

      Cons.hideLoader();
      showMessage(resultSave.errorMessage, 'success');
      UIkit.modal(this.dialog).hide();

    } catch (err) {
      UIkit.notification.closeAll();
      showMessage(i18n.tr(err.message), 'error');
      Cons.hideLoader();
    }
  }

  addButtonListener(){
    this.buttonAddResolutionItem.on('click', e => {
      e.preventDefault();
      this.addResolutionItem();
    });

    this.buttonPassResolution.on('click', e => {
      e.preventDefault();
      this.passResolution();
    });

    if(this.resolution.statusID == 0) {
      this.buttonSaveResolution.on('click', e => {
        e.preventDefault();
        this.saveResolution();
      });
    }

    this.isControl.on('change', e => {
      this.resolution.controlled = e.target.checked;
    });
  }

  addDialogListener(){
    this.dialog.on('shown', () => {
      this.addButtonListener();
    });

    this.dialog.on('hidden', () => {
      this.dialog.remove();
    });
  }

  async init() {
    if(this._doc.hasOwnProperty('documentID')) this.documentID = this._doc.documentID;
    if(this._doc.hasOwnProperty('actionID')) this.actionID = this._doc.actionID;

    this.resolution = this._doc.resolutions.find(x => x.authorID == AS.OPTIONS.currentUser.userid);
    this.resolution.canEdit = this.resolution.canEdit == 'true' ? true : false;
    this.resolution.controlled = this.resolution.controlled == 'true' ? true : false;

    const {systemSettings} = Cons.getAppStore();
    const dict_resolution_text = await appAPI.getDictionaryByCode('resolution');

    this.resolutionText = UTILS.parseDict(dict_resolution_text);
    this.workTypes = systemSettings.resolution_work_types;
    this.completionForms = systemSettings.work_completion_forms;
    this.day_finish_time = systemSettings.day_finish_time.slice(0, 5);
    this.completion_date_for_resolution = systemSettings.completion_date_for_resolution == 'true' ? true : false;
    this.date_resolution_after_finish_document = systemSettings.date_resolution_after_finish_document == 'true' ? true : false;

    this.resolutionText.sort((a,b) => {
      const textA = a.text.toUpperCase();
      const textB = b.text.toUpperCase();
      if (textA < textB) return -1;
      if (textA > textB) return 1;
      return 0;
    });

    this.resolution.items.forEach(item => {
      this.items[item.itemID] = item;
    });

    this.dialog = this.getModal();
    UIkit.modal(this.dialog).show();
    this.addDialogListener();

    if(this.resolution.items.length) {
      this.resolution.items.forEach(item => {
        this.addResolutionItem(item);
      });
    }
  }
}
