const getFileModels = player => {
  const result = [];
  player.model.models[0].modelBlocks[0].forEach(block => {
    if(block.asfProperty.type === "file") result.push(block);
    if(block.asfProperty.type === "table") {
      if(block.modelBlocks.length > 0) {
        block.modelBlocks.forEach(row => {
          row.forEach(tableBlock => {
            if(tableBlock.asfProperty.type === "file") result.push(tableBlock);
          });
        });
      }
    }
  });
  return result;
}

const initOpenFilesInForm = player => {
  const fileModels = getFileModels(player);

  fileModels.forEach(fileModel => {
    const props = fileModel.asfProperty;
    const tmpView = player.view.getViewWithId(props.id, props.ownerTableId, props.tableBlockIndex);

    //отключаем все стандартные события
    setTimeout(() => {
      player.view.container.find(`[data-asformid="file.filename.${props.id}"]`).off();
      fileModel.on('valueChange', () => {
        player.view.container.find(`[data-asformid="file.filename.${props.id}"]`).off();
        return null;
      });
    }, 100);

    //вешаем свое событие
    if(tmpView) {
      tmpView.container.off().on('click', () => {
        if(!fileModel.value) return;
        if(!fileModel.value.hasOwnProperty('identifier')) return;
        const file = new AttachmentFile(fileModel.value.name, fileModel.value.identifier);
        file.open();
      });
    }

  });
}

const filterAgrProcesses = processes => {
  const procCode = ['APPROVAL_ITEM', 'AGREEMENT_ITEM', 'ACQUAINTANCE_ITEM'];
  const result = [];
  function search(p) {
    p.forEach(function(process) {
      if (!process.finished && procCode.includes(process.typeID)) {
        result.push(process);
      }
      if (process.subProcesses.length > 0) search(process.subProcesses);
    });
  }
  search(processes);
  return result;
}

const checkSavedForm = (_doc, handler) => {
  const {formPlayer} = _doc;
  if(formPlayer && formPlayer.model.hasChanges) {
    UIkit.modal.confirm(i18n.tr('Документ был изменен. Сохранить произведенные изменения?'),
    {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}})
    .then(() => {
      if(!formPlayer.model.isValid()) {
        showMessage(i18n.tr("Заполните обязательные поля!"), 'warn');
      } else {
        Cons.showLoader();
        const asfData = formPlayer.model.getAsfData();
        const data = {
          data: '"data" : ' + JSON.stringify(asfData.data),
          form: asfData.form,
          uuid: asfData.uuid
        };
        AS.FORMS.ApiUtils.simpleAsyncPost("rest/api/asforms/form/multipartdata", res => {
          Cons.hideLoader();
          showMessage(`<svg width="35" height="35" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><polyline fill="none" stroke="#32d296" stroke-width="1.1" points="4,10 8,15 17,4"></polyline></svg> ${i18n.tr('Успешно')}`, 'success');
          handler();
        }, "text", data, "application/x-www-form-urlencoded; charset=UTF-8", err => {
          Cons.hideLoader();
          handler();
          showMessage(i18n.tr("Нет прав на редактирование файла"), 'error');
        });
      }
    }, handler);
  } else {
    handler();
  }
}

const closeDocument = _doc => {
  let openDocsWindow;
  if(_doc.type == 'work') {
    openDocsWindow = Cons.getAppStore().openDocsWindow.filter(x => x.actionID !== _doc.actionID);
  } else {
    openDocsWindow = Cons.getAppStore().openDocsWindow.filter(x => x.documentID !== _doc.documentID);
  }

  Cons.setAppStore({openDocsWindow: openDocsWindow});

  _doc.panels.documentWindow.remove();
  _doc.panels.documentPanel.remove();
  if(_doc.formPlayer) _doc.formPlayer.destroy();

  if(!openDocsWindow.length) {
    history.replaceState(null, null, `/${_doc.pathname}`);
  } else {
    let aw = $('.arm-window-document[state="open"]');
    if(aw.length) {
      aw = $(aw[0]);
      aw.attr('arm-active-window', true);

      if(_doc.type == 'work') {
        const actionID = aw.attr('actionid');
        $(`.footer-document[actionid="${actionID}"]`).addClass('arm-active-panel');
        history.replaceState(null, null, `/${_doc.pathname}/?actionID=${actionID}`);
      } else {
        const docID = aw.attr('documentidentifier');
        $(`.footer-document[documentidentifier="${docID}"]`).addClass('arm-active-panel');
        history.replaceState(null, null, `/${_doc.pathname}/?document_identifier=${docID}`);
      }

    } else {
      history.replaceState(null, null, `/${_doc.pathname}`);
    }
  }
}

const resizePanels = _doc => {
  setTimeout(() => {
    const {sendButtonActions, panels} = _doc;
    const {workName, panelButtons, attachmentContainer, signPanel} = panels;
    let h = panelButtons.innerHeight();
    h += 50;
    if(workName) h += workName.innerHeight();
    if(signPanel) h += signPanel.innerHeight();
    if(sendButtonActions && sendButtonActions.length) h += 40;
    attachmentContainer.css({'height': `calc(100% - ${h}px)`});
  }, 500);
}

const updateWorkInfo = async (actionID, _doc) => {
  return new Promise(async resolve => {

    _doc.workInfo = await appAPI.getWorkInfo(actionID);
    if(_doc.workInfo && _doc.documentID) _doc.workInfo.documentID = _doc.documentID;

    if(_doc.type == 'work' || _doc.hasOwnProperty('workInfo')) {
      _doc.docActions = await appAPI.getWorkActions(actionID);

      _doc.sendButtonActions = _doc.docActions.filter(x => ['TRANSMIT', 'REASSIGN', 'SEND'].includes(x.action));
      _doc.resolution = _doc.docActions.find(x => ['RESOLUTION'].includes(x.action));
    }

    if(_doc.dataUUID) {
      if(_doc.workInfo) _doc.workInfo.dataUUID = _doc.dataUUID;
      _doc.activePanel = 'form';
      _doc.rccVisible = false;
    } else {
      if(_doc.workInfo) _doc.documentName = _doc.workInfo.name;
      _doc.activePanel = 'rcc';
      _doc.rccVisible = true;
    }

    resolve(_doc);
  });
}

const renderSwitchWork = _doc => {
  const {panels, processResponsible} = _doc;

  if(panels.hasOwnProperty('panelSwitchWork')) return;

  panels.panelSwitchWork = $('<div>', {style: "display: flex; justify-content: end;"});
  panels.workName.append(panels.panelSwitchWork);

  let index = 1;
  const buttonLeft = $('<a href="" uk-icon="icon: triangle-left"></a>');
  const buttonRight = $('<a href="" uk-icon="icon: triangle-right"></a>');
  const numberWork = $('<span>');

  const updateData = isWork => {
    numberWork.text(`${index}/${processResponsible.length}`);
    if(isWork) {
      const {actionID} = processResponsible[index - 1];
      updateWorkInfo(actionID, _doc).then(() => {
        new ButtonsActions(_doc);
        setWorkInfo(_doc);
      });
    }
  }

  updateData();

  panels.panelSwitchWork.append(buttonLeft, numberWork, buttonRight);

  buttonLeft.on('click', e => {
    e.preventDefault();
    index--;
    if(index < 1) {
      index = 1;
    } else {
      updateData(true);
    }
  });

  buttonRight.on('click', e => {
    e.preventDefault();
    index++;
    if(index > processResponsible.length) {
      index = processResponsible.length;
    } else {
      updateData(true);
    }
  });
}

const setWorkInfo = _doc => {
  const {workInfo, documentName, panels, processResponsible} = _doc;

  if(workInfo) {
    const {name, author, user, start_date, finish_date} = workInfo;

    if(!panels.hasOwnProperty('panelWorkInfo')) {
      panels.panelWorkInfo = $('<div>', {style: "display: flex; flex-direction: column; gap: 5px;"});
      panels.workName.append(panels.panelWorkInfo);
    }

    panels.panelWorkInfo.empty().append(
      `<span id="workNameLabel" class="work_name">${name}</span>`,
      `<span id="workAuthorLabel" class="info">${i18n.tr("Автор:")} ${author.name}</span>`,
      `<span id="workUserLabel" class="info">${i18n.tr("Ответственный:")} ${user.name}</span>`,
      `<span id="workStartDateLabel" class="info">${i18n.tr("Дата начала")}: ${UTILS.customFormatDate(start_date)}</span>`,
      `<span id="workFinishDateLabel" class="info">${i18n.tr("Дата завершения")}: ${UTILS.customFormatDate(finish_date)}</span>`
    );

    if(processResponsible && processResponsible.length > 1) renderSwitchWork(_doc);

  } else {
    panels.workName.text(documentName);
  }
}

const buttonSort = _doc => {
  const {mobileMenu, panelButtons} = _doc.panels;

  function s(a, b) {
    let idA = $(a).attr("id");
    let idB = $(b).attr("id");
    if (idA > idB) return 1;
    if (idA < idB) return -1;
    return 0;
  }
  const mobileMenuContent = mobileMenu.find('.arm-mobile-two-panel');
  const buttons = panelButtons.find('.window-action-button');
  buttons.sort(s);
  $(buttons).appendTo(panelButtons);
  const buttons2 = mobileMenuContent.find('.window-action-button');
  buttons2.sort(s);
  $(buttons2).appendTo(mobileMenuContent);
}

const createButton = (_doc, name, id, handler, greenButton) => {
  const {mobileMenu, panelButtons} = _doc.panels;
  const mobileMenuContent = mobileMenu.find('.arm-mobile-two-panel');
  const button = $(`<button id="${id}" class="uk-button margined uk-button-default window-action-button fonts">`)
  .css({
    'width': '100%',
    'white-space': 'nowrap',
    'text-overflow': 'ellipsis',
    'overflow': 'hidden',
    'padding': '0 5px',
  })
  .attr('uk-tooltip', `title: ${name}; duration: 300;`)
  .html(name)
  .on('click', e => {
    e.preventDefault();
    e.target.blur();

    if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
      mobileMenu.trigger('hideShowMenu');
    }

    handler();
  });
  if(greenButton) button.addClass('window-action-button-green');
  panelButtons.append(button);
  button.clone(true).appendTo(mobileMenuContent);
  buttonSort(_doc);
}

const saveFormData = (_doc, handler) => {
  const {formPlayer} = _doc;
  if(!formPlayer.model.isValid()) {
    showMessage(i18n.tr("Заполните обязательные поля!"), 'warn');
  } else {
    Cons.showLoader();
    try {
      const asfData = formPlayer.model.getAsfData();
      const data = {
        data: '"data" : ' + JSON.stringify(asfData.data),
        form: asfData.form,
        uuid: asfData.uuid
      };
      AS.FORMS.ApiUtils.simpleAsyncPost("rest/api/asforms/form/multipartdata", res => {
        Cons.hideLoader();
        showMessage(`<svg width="35" height="35" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><polyline fill="none" stroke="#fff" stroke-width="1.1" points="4,10 8,15 17,4"></polyline></svg> ${i18n.tr('Успешно')}`, 'success');
        formPlayer.model.hasChanges = false;
        if(handler) handler();
      }, "text", data, "application/x-www-form-urlencoded; charset=UTF-8", err => {
        Cons.hideLoader();
        showMessage(i18n.tr("Нет прав на редактирование файла"), 'error');
      });
    } catch (err) {
      Cons.hideLoader();
      showMessage(i18n.tr("Ошибка сохранения данных по форме"), 'error');
      console.log(err.message);
    }
  }
}

const printForm = content => {
  const css = '<link rel="stylesheet" href="synergyForms.css" type="text/css" />';
  const WinPrint = window.open();
  WinPrint.document.write('');
  WinPrint.document.write(css);
  WinPrint.document.write(content.innerHTML);
  WinPrint.document.write('');
  WinPrint.document.close();
  WinPrint.focus();
  WinPrint.print();
}

const cutText = text => {
  if(text.length > 100) return text.slice(0, 100) + '...';
  return text;
}

const activateDocument = async _doc => {
  const {formPlayer} = _doc;

  if(!formPlayer.model.isValid()) {
    showMessage(i18n.tr("Заполните обязательные поля!"), 'warn');
    return;
  }

  Cons.showLoader();
  try {
    const asfData = formPlayer.model.getAsfData();
    await AS.FORMS.ApiUtils.saveAsfData(asfData.data, asfData.form, asfData.uuid);
    await appAPI.activateDoc(asfData.uuid);

    Cons.hideLoader();
    showMessage(`<svg width="35" height="35" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><polyline fill="none" stroke="#49B785" stroke-width="1.1" points="4,10 8,15 17,4"></polyline></svg> ${i18n.tr('Успешно')}`, 'success');

    //закрыть окно после активации
    closeDocument(_doc);

  } catch (err) {
    Cons.hideLoader();
    showMessage(i18n.tr("Произошла ошибка при создании заявки, обратитесь к администратору"), 'error');
    console.log(err.message);
  }
}

const getUserWork = (processes, userID) => {
  const result = [];
  function search(p) {
    p.forEach(function(process) {
      if (!process.finished &&
        process.actionID != "" &&
        (process.responsibleUserID == userID || process.authorID == userID)
      ) {
        result.push(process);
      }
      if (process.subProcesses.length > 0) search(process.subProcesses);
    });
  }
  search(processes);

  return result.sort((a, b) => UTILS.parseDateTime(b.started) - UTILS.parseDateTime(a.started));
}

const getResponsibleUserWork = processes => {
  const result = [];
  function search(p) {
    p.forEach(function(process) {
      if (!process.finished &&
        process.actionID != "" &&
        process.responsibleUserID == AS.OPTIONS.currentUser.userid
      ) {
        result.push(process);
      }
      if (process.subProcesses.length > 0) search(process.subProcesses);
    });
  }
  search(processes);

  return result.sort((a, b) => UTILS.parseDateTime(b.started) - UTILS.parseDateTime(a.started));
}

const setProgressWork = async (_doc, progress) => {
  const {actionID} = _doc;
  if(progress == 100) {
    const msgConfirm = i18n.tr("Вы действительно хотите завершить данную работу? Все дочерние работы так же будут завершены.");
    const msgSuccess = i18n.tr("Работа завершена");

    UIkit.modal.confirm(msgConfirm, {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}}).then(async () => {
      const resultFinish = await appAPI.setProgressWork(progress, actionID);
      if(resultFinish) {
        showMessage(msgSuccess, 'success');
        closeDocument(_doc);
      } else {
        showMessage(i18n.tr('Произошла ошибка при завершении работы'), 'error');
      }
    }, () => {
      return;
    });
  } else {
    const resultFinish = await appAPI.setProgressWork(progress, actionID);
    if(resultFinish) {
      closeDocument(_doc);
    } else {
      showMessage(i18n.tr('Произошла ошибка при изменении прогресса работы'), 'error');
    }
  }
}

const finishWork = async (_doc) => {
  try {
    const {formPlayer, workInfo, documentID} = _doc;
    if(formPlayer && formPlayer.model.getErrors().length) throw new Error(i18n.tr('Заполните обязательные поля'));

    checkSavedForm(_doc, async () => {
      const msgConfirm = i18n.tr('Вы действительно хотите завершить работу?');
      const {actionID, author, user, completionForm} = workInfo;
      const childDocuments = await appAPI.getChildDocuments(documentID);
      workInfo.childDocuments = childDocuments;

      if(AS.OPTIONS.currentUser.userid == author.id && user.id != author.id) {
        UIkit.modal.confirm(msgConfirm, {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}})
        .then(() => {
          _WORK.finishWork(actionID, _doc);
        }, null);
      } else {
        if(completionForm) {
          const {CompletionFormType, completionFormName, CompletionFormInfo} = completionForm;

          switch (CompletionFormType) {
            case "FORM": _WORK.finishForm(actionID, CompletionFormInfo, _doc); break;
            case "COMMENT": _WORK.finishComment(actionID, _doc); break;
            case "FILE": _WORK.finishFile(actionID, _doc); break;
            case "DOCUMENT": _WORK.finishDocument(actionID, childDocuments, _doc); break;
            case "NOTHING":
              UIkit.modal.confirm(msgConfirm, {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}})
              .then(() => {
                _WORK.finishWork(actionID, _doc);
              }, null);
              break;
          }

        } else {
          UIkit.modal.confirm(msgConfirm, {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}})
          .then(() => {
            setProgressWork(_doc, 100);
          }, null);
        }
      }
    });

  } catch (error) {
    Cons.hideLoader();
    showMessage(i18n.tr("Произошла ошибка при завершении работы"), 'error');
    console.log(error);
  }
}

const signDocument = async (documentID, signButton) => {
  try {
    NCALayer.sign('SIGN', documentID, async result => {
      Cons.showLoader();

      try {
        const signResult = await AS.FORMS.ApiUtils.simpleAsyncPost("rest/api/docflow/sign", null, null, {
          documentID,
          rawdata: result.dataForSign,
          signdata: result.signedData,
          certificate: result.certificate,
          certID: result.certID
        });

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

        Cons.hideLoader();
        showMessage(i18n.tr('Документ успешно подписан ЭЦП'), 'success');
        signButton.hide();
      } catch (e) {
        Cons.hideLoader();
        showMessage(i18n.tr(e.message), 'error');
      }

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

const setField = (from, modelTo, collation_type = null, label = null) => {
  if(from) {
    switch (from.type) {
      case 'textbox':
      case 'textarea':
        if(modelTo && from.hasOwnProperty('value') && from.value) {
          const currentValue = modelTo.getValue();

          switch (collation_type) {
            case 'PREFIX':
              if(currentValue && currentValue != '') {
                if(label && label != '') {
                  modelTo.setValue(`${label} ${from.value}`);
                } else {
                  modelTo.setValue(`${currentValue} ${from.value}`);
                }
              } else {
                if(label && label != '') {
                  modelTo.setValue(`${label} ${from.value}`);
                } else {
                  modelTo.setValue(from.value);
                }
              }
              break;
            case 'POSTFIX':
              if(currentValue && currentValue != '') {
                if(label && label != '') {
                  modelTo.setValue(`${from.value} ${label}`);
                } else {
                  modelTo.setValue(`${from.value} ${currentValue}`);
                }
              } else {
                if(label && label != '') {
                  modelTo.setValue(`${from.value} ${label}`);
                } else {
                  modelTo.setValue(from.value);
                }
              }
              break;
            default: modelTo.setValue(from.value);
          }

        } else {
          if(modelTo) modelTo.setValue(null);
        }
        break;
      case 'check':
        if(modelTo && from.hasOwnProperty('values')) {
          modelTo.setValue(from.values);
        } else {
          if(modelTo) modelTo.setValue(null);
        }
        break;
      case 'entity':
        if(modelTo && from.hasOwnProperty('key') && from.key && from.key !== 'null') {
          switch (modelTo.asfProperty.config.entity) {
            case "users":
              modelTo.setValue({
                personID: from.key,
                personName: from.value
              });
              break;
            case "departments":
              modelTo.setValue({
                departmentId: from.key,
                departmentName: from.value
              });
              break;
            case "positions":
              modelTo.setValue({
                elementID: from.key,
                elementName: from.value
              });
              break;
          }
        } else {
          if(modelTo) modelTo.setValue(null);
        }
        break;
      default:
        if(modelTo && from.hasOwnProperty('key') && from.key) {
          modelTo.setValue(from.key);
        } else {
          if(modelTo) modelTo.setValue(null);
        }
    }
  } else {
    if(modelTo) modelTo.setValue(null);
  }
}

const removeRow = tableModel => {
  for(let numb in tableModel.getBlockNumbers()) tableModel.removeRow(numb);
}

const initMatching = async _doc => {
  Cons.showLoader();
  const {matchingParam, formPlayer} = _doc;
  const {currentRegistryCode, parentDocumentID, parentDataUUID} = matchingParam;
  const currentDocumentID = await appAPI.getDocumentIdentifier(_doc.dataUUID);

  await appAPI.setChildDocuments(parentDocumentID, [currentDocumentID]);

  if(parentDataUUID) {
    const parentDocInfo = await appAPI.getDocumentInfo(parentDocumentID);
    const parentRegInfo = await appAPI.getRegistryInfoByID(parentDocInfo.registryID);
    const collationInfo = await appAPI.getCollationInfo(parentRegInfo.code, currentRegistryCode);
    const parentAsfData = await appAPI.loadAsfData(parentDataUUID);

    Cons.hideLoader();

    for(let i = 0; i < collationInfo.length; i++) {
      const {collation_fields} = collationInfo[i];

      for(let j = 0; j < collation_fields.length; j++) {
        const {in_field, out_field, collation_type, label} = collation_fields[j];
        const from = parentAsfData.data.find(x => x.id === in_field);

        if(out_field.indexOf('.') != -1) {
          const tableID = out_field.split('.')[0];
          const fieldTableID = out_field.split('.')[1];
          const modelTable = formPlayer.model.playerModel.getModelWithId(tableID);

          if(modelTable) {
            const toBlock = modelTable.createRow();
            const tableModelOutField = formPlayer.model.playerModel.getModelWithId(fieldTableID, tableID, toBlock.tableBlockIndex);

            if(from && from.type == "appendable_table") {
              const fromTableData = UTILS.parseAsfTable(from);

              for(let k = 0; k < fromTableData.length; k++) {
                const fromBlock = fromTableData[k];

                for(const filedID in fromBlock) {
                  if(fieldTableID != filedID) continue;
                  const fromField = {id: filedID, ...fromBlock[filedID]}
                  setField(fromField, tableModelOutField, collation_type, label);
                }
              }

            } else {
              setField(from, tableModelOutField, collation_type, label);
            }
          }

        } else {
          const modelTo = formPlayer.model.playerModel.getModelWithId(out_field);

          if(from && from.type == "appendable_table" && modelTo && modelTo.asfProperty.type == "table") {

            removeRow(modelTo);
            const fromTableData = UTILS.parseAsfTable(from);

            for(let k = 0; k < fromTableData.length; k++) {
              const fromBlock = fromTableData[k];
              const toBlock = modelTo.createRow();

              for(const filedID in fromBlock) {
                const tableModelOutField = formPlayer.model.playerModel.getModelWithId(filedID, out_field, toBlock.tableBlockIndex);
                const fromField = {id: filedID, ...fromBlock[filedID]}
                setField(fromField, tableModelOutField, collation_type, label);
              }
            }

          } else {
            setField(from, modelTo, collation_type, label);
          }
        }

      }
    }
  } else {
    Cons.hideLoader();
  }

}

const createChildDocument = async _doc => {
  try {
    Cons.showLoader();
    const {documentID: parentDocumentID, dataUUID: parentDataUUID, workInfo} = _doc;
    const {completionForm} = workInfo;

    if(!parentDocumentID) throw new Error('Произошла ошибка при создании документа');

    const {CompletionFormInfo, completionFormName} = completionForm;
    const regInfo = await appAPI.getRegistryInfo(CompletionFormInfo.registryCode);
    if(!regInfo) throw new Error(i18n.tr('При создании записи произошла ошибка. Не удалось плучить информацию по реестру.'));
    if(regInfo.rr_create != "Y") throw new Error(i18n.tr('У вас нет прав на создание записи'));

    const doc = await appAPI.createDoc(CompletionFormInfo.registryCode);
    if(!doc) throw new Error(i18n.tr('Произошла ошибка при создании данного типа документа'));

    Cons.hideLoader();

    const matchingParam = {currentRegistryCode: CompletionFormInfo.registryCode, parentDocumentID, parentDataUUID};

    const eventParam = {
      type: 'document',
      documentID: doc.documentID,
      editable: true,
      matchingParam
    };

    $('#root-panel').trigger({type: 'custom_open_document', eventParam});

  } catch (e) {
    Cons.hideLoader();
    console.log(e);
    showMessage(e.message, 'error');
  }
}

const registryReply = async (_doc, replyRegistryInfo) => {
  try {
    Cons.showLoader();

    const {documentID: parentDocumentID, dataUUID: parentDataUUID} = _doc;

    if(!parentDocumentID) throw new Error('Произошла ошибка при создании документа');

    if(!replyRegistryInfo) throw new Error(i18n.tr('При создании записи произошла ошибка. Не удалось плучить информацию по реестру.'));
    if(replyRegistryInfo.rr_create != "Y") throw new Error(i18n.tr('У вас нет прав на создание записи'));

    const doc = await appAPI.createDoc(replyRegistryInfo.code);
    if(!doc) throw new Error(i18n.tr('Произошла ошибка при создании данного типа документа'));

    Cons.hideLoader();

    const matchingParam = {currentRegistryCode: replyRegistryInfo.code, parentDocumentID, parentDataUUID};

    const eventParam = {
      type: 'document',
      documentID: doc.documentID,
      editable: true,
      matchingParam
    };

    $('#root-panel').trigger({type: 'custom_open_document', eventParam});

  } catch (e) {
    Cons.hideLoader();
    console.log(`ERROR registryReply ${e.message}`);
    showMessage(e.message, 'error');
  }
}

const chekResolutionItem = _doc => {
  const {resolutions = []} = _doc;
	let result = false;
	resolutions.forEach(resolution => {
    const {items, statusID} = resolution;
  	if(statusID != 0 && items.length) result = true;
  });
  return result;
}

const getUserFullName = str => {
  const arr = str.split(' ');
  const fio = arr[0].substr(0, 1).toUpperCase() + arr[0].substr(1) + ' ' + arr[1].substr(0, 1).toUpperCase() + '.';
  return arr[2] ? fio + ' ' + arr[2].substr(0, 1).toUpperCase() + '.' : fio;
}

class DocumentParams {
  constructor(){
    this.#init([...arguments]);
  }

  #init(args){
    for(let x = 0; x < args.length; x++) {
      const arg = args[x];
      if(arg && arg instanceof Object && !Array.isArray(arg)) for(const key in arg) this[key] = arg[key];
    }
  }
}

class Document {
  constructor(_doc) {
    this._doc = _doc;
    this.dataUUID = _doc.dataUUID;
    this.documentID = _doc.documentID;
    this.workName = _doc.panels.workName;
    this.panelButtons = _doc.panels.panelButtons;
    this.process = _doc.process;
    this.registryInfo = _doc.registryInfo;

    this.init();
  }

  async renderButtons(){
    const {userid} = AS.OPTIONS.currentUser;
    const {workInfo, resolution} = this._doc;

    if(workInfo) {
      const {parent_process, user, author, completionForm, name, finished} = workInfo;

      if(finished) return;

      if(completionForm) {
        const {CompletionFormInfo, CompletionFormType} = completionForm;

        if(CompletionFormType == "DOCUMENT") {
          const buttonName = CompletionFormInfo['button-name'];
          if(CompletionFormInfo.child && workInfo.childDocuments && !workInfo.childDocuments.length) {
            createButton(this._doc, buttonName, 'arm_action_button2', () => {
              createChildDocument(this._doc);
            }, true);
          } else {
            createButton(this._doc, buttonName, 'arm_action_button4', () => {
              createChildDocument(this._doc);
            }, false);
          }
        }
      } else if(this.registryInfo) { //кнопка реестра ответа
        const {reply_btn_name, reply_registryID} = this.registryInfo;
        if(reply_registryID && reply_registryID != "") {
          const replyRegistryInfo = await appAPI.getRegistryInfoByID(reply_registryID);
          if(replyRegistryInfo.rr_create == "Y") {
            createButton(this._doc, reply_btn_name, 'arm_action_button5', () => {
              registryReply(this._doc, replyRegistryInfo);
            }, false);
          }
        }
      }

      if(resolution) {
        createButton(this._doc, resolution.label, 'arm_action_button6', () => {
          new Resolution(this._doc);
        }, false);
      }

      if(AS.OPTIONS.currentUser.userid == user.id) {
        switch (parent_process) {
          case 'null':
          case 'assignment-single': //Завершить
            createButton(this._doc, i18n.tr("Завершить"), 'arm_action_button3', () => {
              const {dataUUID, mainDataUUID} = this._doc;
              if(dataUUID && dataUUID != mainDataUUID) {
                this._doc.formPlayer.showFormData(null, null, mainDataUUID);
                setTimeout(() => {
                  finishWork(this._doc);
                }, 500);
              } else {
                finishWork(this._doc);
              }
            }, true);
           break;
          case 'approval-single': //Утвердить
            createButton(this._doc, i18n.tr("Утвердить"), 'arm_action_button7', () => {
              _WORK.finishProcess(workInfo, this._doc);
            }, false);
            break;
          case 'agreement-single': //Согласовать
            createButton(this._doc, i18n.tr("Согласовать"), 'arm_action_button7', () => {
              _WORK.finishProcess(workInfo, this._doc);
            }, false);
            break;
          case 'acquaintance-single': //Ознакомиться
            createButton(this._doc, i18n.tr("Ознакомиться"), 'arm_action_button7', () => {
              _WORK.finishProcess(workInfo, this._doc);
            }, false);
            break;
          case 'resolution-action-single': console.log('Резолюция? хммм....'); break; // Резолюция
        }
      } else if(AS.OPTIONS.currentUser.userid == author.id) {
        if(completionForm && completionForm.hasOwnProperty('is_result_free') && !completionForm.is_result_free) {
          createButton(this._doc, i18n.tr("Завершить"), 'arm_action_button3', () => {
            _WORK.acceptWork(this._doc);
          }, true);
        } else {
          createButton(this._doc, i18n.tr("Завершить"), 'arm_action_button3', () => {
            const {dataUUID, mainDataUUID} = this._doc;
            if(dataUUID && dataUUID != mainDataUUID) {
              this._doc.formPlayer.showFormData(null, null, mainDataUUID);
              setTimeout(() => {
                finishWork(this._doc);
              }, 500);
            } else {
              finishWork(this._doc);
            }
          }, true);
        }
      }
    }

    resizePanels(this._doc);
  }

  init(refresh){
    if(refresh) {
      this.renderButtons();
    } else {
      this.renderButtons();
      if(this._doc.formPlayer) {
        setTimeout(() => {
          this._doc.formPlayer.model.hasChanges = false;
        }, 1000);
      }
    }
  }

}

class ButtonsActions {
  constructor(_doc) {
    this._doc = _doc;
    this.init();
  }

  async renderSignButton() {
    const {userid} = AS.OPTIONS.currentUser;
    const signList = await appAPI.getSignList(this._doc.documentID);
    const acqAgrProc = filterAgrProcesses(this._doc.process);
    const isSign = signList.find(x => x.userID == userid);

    if(!acqAgrProc.length && !isSign) {

      const {panelInfo} = this._doc.panels;
      const signPanel = $('<div>');
      const signButton = $('<button>', {class: "uk-button margined uk-button-default window-action-button fonts"});
      const buttonName = i18n.tr('Подписать');

      signPanel.css({
        'display': 'flex',
        'flex-direction': 'column',
        'width': '100%',
        'align-items': 'center',
        'padding': '0 15px',
      })

      signButton.css({
        'width': '100%',
        'white-space': 'nowrap',
        'text-overflow': 'ellipsis',
        'overflow': 'hidden',
        'padding': '0 5px',
      })
      .attr('uk-tooltip', `title: ${buttonName}; duration: 300;`)
      .html(buttonName);

      this._doc.panels.signPanel = signPanel;
      signPanel.append(signButton);
      panelInfo.append(signPanel);

      signButton.on('click', e => {
        e.preventDefault();
        e.target.blur();
        signDocument(this._doc.documentID, signButton);
      });

    }
  }

  async refresh(init) {
    this.panelButtons.empty();

    const {docActions, process, docInfo} = this._doc;
    const run = docActions.find(x => x.operation == 'RUN');

    if(this._doc.formPlayer) {

      // Если запись не отправлена, создаем кнопку с активацией документа
      if(run) {
        if(this._doc.formPlayer.model.hasChanges) {
          this._doc.saveButton.show();
          this._doc.saveButtonMobile.show();
        } else {
          this._doc.saveButton.hide();
          this._doc.saveButtonMobile.hide();
        }
        this._doc.editReadFormButton.show();
        this._doc.editReadFormButtonMobile.show();

        if(!this.registryInfo) {
          //в случае если нет информации по реестру
          createButton(this._doc, run.label, 'arm_action_button1', () => activateDocument(this._doc), true);
        } else if(this.registryInfo.rr_create == 'Y') {
          //Если есть права на создание
          createButton(this._doc, run.label, 'arm_action_button1', () => activateDocument(this._doc), true);
        }
      } else {
        const acqAgrProc = filterAgrProcesses(process);

        if(docInfo && docInfo.registered != "true" && !acqAgrProc.length) {
          if(this._doc.formPlayer.model.hasChanges) {
            this._doc.saveButton.show();
            this._doc.saveButtonMobile.show();
          } else {
            this._doc.saveButton.hide();
            this._doc.saveButtonMobile.hide();
          }

          this._doc.editReadFormButton.show();
          this._doc.editReadFormButtonMobile.show();
        }

      }
    }

    if(!run) {
      if(init) {
        this.actionButtons = new Document(this._doc);
      } else {
        this.actionButtons.init(true);
      }
    }

    this.renderSignButton();
    resizePanels(this._doc);
  }

  init(){
    this.documentID = this._doc.documentID;
    this.dataUUID = this._doc.dataUUID;
    this.panelButtons = this._doc.panels.panelButtons;
    this.editReadFormButton = this._doc.editReadFormButton;
    this.workName = this._doc.panels.workName;
    this.registryCode = this._doc.registryCode;
    this.registryInfo = this._doc.registryInfo;
    this.actionButtons = null;

    //Если нет прав на редактирование
    if(this.registryInfo && this.registryInfo.rr_edit != 'Y') this.editReadFormButton.hide();

    this.refresh(true);
  }
}

class ARMDocumentButtons {
  constructor(_doc) {
    this._doc = _doc;
    this.init();
  }

  async canEdit() {
    const {process, docInfo, workInfo, formPlayer, registryInfo} = this._doc;
    const acqAgrProc = filterAgrProcesses(process);

    if(!formPlayer) return false;
    if(!docInfo) return false;
    if(docInfo.registered == "true") return false;
    if(registryInfo.rr_edit != "Y") return false;

    if(workInfo) {
      const {actionID, has_subprocesses, parent_process} = workInfo;
      const procCode = ['approval-single', 'agreement-single', 'acquaintance-single'];
      if(procCode.includes(parent_process)) return false;

      if(has_subprocesses == "true") {
        const subworks = await appAPI.getSubworks(actionID);
        const filtered = subworks.filter(x => procCode.includes(x.parent_process));
        if(filtered.length) return false;
      }
    }

    return true;
  }

  async changcheButtons(){
    if(!this._doc.formPlayer) return false;

    Cons.showLoader();
    const can_edit = await this.canEdit();
    Cons.hideLoader();

    if(!can_edit) {
      this.saveButton.hide();
      this.saveButtonMobile.hide();
      this.editReadFormButton.hide();
      this.editReadFormButtonMobile.hide();
    } else {
      if(this._doc.editable) {
        this.editReadFormButton.text('description');
        this.editReadFormButtonMobile.text('description');
        this.editReadFormButton.attr('uk-tooltip', `title: ${i18n.tr('Просмотр')}; duration: 300;`);

        this.printButton.hide();
        this.printButtonMobile.hide();
        this.saveButton.show();
        this.saveButtonMobile.show();

      } else {
        this.editReadFormButton.text('edit');
        this.editReadFormButtonMobile.text('edit');
        this.editReadFormButton.attr('uk-tooltip', `title: ${i18n.tr('Редактировать')}; duration: 300;`);

        this.printButton.show();
        this.printButtonMobile.show();
        if(this._doc.formPlayer.model.hasChanges) {
          this.saveButton.show();
          this.saveButtonMobile.show();
        } else {
          this.saveButton.hide();
          this.saveButtonMobile.hide();
        }
      }
    }

  }

  renderPanelActions(){
    const buttonsPanel = $('<div>', {class: 'arm-panel-buttons'});
    const oneMobilePanel = $('<div>', {class: 'arm-mobile-one-panel'});
    this.menuIcon = $('<div>', {class: 'menu__icon'}).append('<span>');

    this.saveButton = $('<span class="material-icons action-icon-button" style="display: none;">save</span>');
    this.printButton = $('<span class="material-icons action-icon-button">print</span>');
    this.editReadFormButton = $('<span class="material-icons action-icon-button">edit</span>');

    this.saveButtonMobile = $('<span class="material-icons action-icon-button mobile" style="display: none;">save</span>');
    this.printButtonMobile = $('<span class="material-icons action-icon-button mobile">print</span>');
    this.editReadFormButtonMobile = $('<span class="material-icons action-icon-button mobile">edit</span>');

    this.saveButton.attr('uk-tooltip', `title: ${i18n.tr('Сохранить')}; duration: 300;`);
    this.printButton.attr('uk-tooltip', `title: ${i18n.tr('Печать')}; duration: 300;`);

    oneMobilePanel.append(this.printButtonMobile, this.editReadFormButtonMobile, this.saveButtonMobile);
    buttonsPanel.append(
      $('<div>').append(this.saveButton, this.printButton),
      $('<div>').append(this.editReadFormButton)
    );
    this.panelActions.append(this.menuIcon, buttonsPanel);
    this.mobileMenu.append(oneMobilePanel, $('<div>', {class: 'arm-mobile-two-panel'}));

    this._doc.editReadFormButton = this.editReadFormButton;
    this._doc.editReadFormButtonMobile = this.editReadFormButtonMobile;
    this._doc.saveButton = this.saveButton;
    this._doc.saveButtonMobile = this.saveButtonMobile;

    this.changcheButtons();
  }

  hideShowMobileMenu(){
    this.menuIcon.toggleClass('_active');
    this.mobileMenu.toggleClass('_active');
    this.formPanel.toggleClass('_lock');
  }

  editRead(e){
    e.preventDefault();
    e.target.blur();
    if(!this._doc.formPlayer) return;

    this._doc.editable = !this._doc.editable;
    this._doc.formPlayer.view.setEditable(this._doc.editable);
    this.changcheButtons();
  }

  save(e){
    e.preventDefault();
    e.target.blur();
    saveFormData(this._doc);
  }

  print(e){
    e.preventDefault();
    e.target.blur();
    if(!this._doc.formPlayer) return;

    if(this._doc.formPlayer.model.hasPrintable) {
      const dataUUID = this._doc.formPlayer.model.asfDataId;
      window.open(`../Synergy/rest/asforms/template/print/form?format=pdf&dataUUID=${dataUUID}`);
    } else {
      printForm(this._doc.formPlayer.view.container[0]);
    }
  }

  addListeners(){
    this.editReadFormButton.on('click', e => {
      this.editRead(e);
    });
    this.editReadFormButtonMobile.on('click', e => {
      this.editRead(e);
      this.hideShowMobileMenu();
    });

    this.saveButton.on('click', e => {
      this.save(e);
    });
    this.saveButtonMobile.on('click', e => {
      this.save(e);
      this.hideShowMobileMenu();
    });

    this.printButton.on('click', e => {
      this.print(e);
    });
    this.printButtonMobile.on('click', e => {
      this.print(e);
      this.hideShowMobileMenu();
    });

    this.menuIcon.on('click', e => {
      this.hideShowMobileMenu();
    });

    this.mobileMenu.on('hideShowMenu', e => {
      this.hideShowMobileMenu();
    });

    this.buttonDocumentRCC.on('click', e => {
      const {currentFormContainer, rccContainer, attachmentViewContainer} = this._doc.panels;

      if(this._doc.rccVisible) {
        this.buttonDocumentRCC.removeClass('pressed');
        rccContainer.removeClass('active');
        if(this._doc.activePanel == 'form') {
          currentFormContainer.addClass('active');
        } else {
          attachmentViewContainer.addClass('active');
        }
      } else {
        this.buttonDocumentRCC.addClass('pressed');
        currentFormContainer.removeClass('active');
        rccContainer.addClass('active');
        attachmentViewContainer.removeClass('active');
        new _RCC(this._doc.docInfo, this._doc.panels.rccContainer);
      }

      this._doc.rccVisible = !this._doc.rccVisible;

    });
  }

  initDropdowMenu(){
    const { sendButtonActions, documentID, workInfo } = this._doc;
    const { dropdownList } = this._doc.panels;

    if(!sendButtonActions || !sendButtonActions.length) return;
    let actionID = null;
    if(workInfo) actionID = workInfo.actionID;

    sendButtonActions.forEach(item => {
      const li = $('<li>');
      const a = $(`<a href="#">${item.label}</a>`);

      li.append(a);
      dropdownList.append(li);

      a.on('click', async e => {
        e.preventDefault();
        e.target.blur();
        try {
          if(item.action == 'TRANSMIT') {
            _WORK.transfer(workInfo);
          } else {
            const resultSendWork = await _WORK.startRoute({...item, actionID, documentID});
            if(resultSendWork.errorCode == 0) closeDocument(this._doc);
          }
        } catch (err) {
          showMessage(err.message, 'error');
        }
      });
    });
  }

  init(){
    const {panels} = this._doc;

    this.panelButtons = panels.panelButtons;
    this.panelActions = panels.panelActions;
    this.mobileMenu = panels.mobileMenu;
    this.formPanel = panels.formPanel;
    this.buttonDocumentRCC = panels.buttonDocumentRCC;
    this.editReadFormButton = null;
    this.saveButton = null;
    this.printButton = null;

    setWorkInfo(this._doc);
    this.initDropdowMenu();
    this.renderPanelActions();
    this.addListeners();

    new ButtonsActions(this._doc);
  }
}

class ARMDocument {
  constructor(panel, _doc) {
    this.panel = panel;
    this._doc = _doc;
    this.window = null;
    this.state = null;

    this.init();
  }

  async getPlayerModel(){
    const me = this;
    return new Promise(resolve => {
      let timerId;
      timerId = setTimeout(function tick() {
        if(me._doc.formPlayer.hasOwnProperty("model") && me._doc.formPlayer.model.hasOwnProperty('nodeId')) {
          clearTimeout(timerId);
          timerId = null;
          resolve(me._doc.formPlayer.model);
        } else {
          timerId = setTimeout(tick, 200);
        }
      }, 100);
    });
  }

  async getFileVersions(){
    let playerModel = await this.getPlayerModel();
    if(!playerModel) playerModel = await this.getPlayerModel();

    const {nodeId: identifier, formName: fullName} = playerModel;
    const headers = [i18n.tr('Дата'), i18n.tr('Автор'), i18n.tr('Длина'), i18n.tr('Комментарий'), i18n.tr('Действие')];
    const table = $('<table>', {class: "uk-table uk-table-small wf-versions-table uk-table-responsive"});
    const thead = $('<thead>');
    const tbody = $('<tbody>');
    const theadTr = $('<tr>');

    headers.forEach(header => theadTr.append(`<th>${header}</th>`));
    thead.append(theadTr);
    table.append(thead).append(tbody);

    const description = await appAPI.getFileDescription(identifier);
    if(description && description.hasOwnProperty('versions')) {
      description.versions.forEach(item => {
        const {modified, author, length, comment} = item;
        const tr = $('<tr>');
        tbody.append(tr);

        tr.on('click', e => {
          tbody.find('tr').removeClass('select');
          tr.addClass('select');
        });

        tr.append(
          `<td>${modified}</td>`,
          `<td>${author}</td>`,
          `<td>${i18n.tr('{0} Байт').replace('{0}', length)}</td>`,
          `<td>${comment}</td>`
        );

        const lastTd = $('<td>');

        const buttonDownloadVersion = $('<button>', {class: 'uk-button uk-button-default uk-button-small button-switch pressed'});
        buttonDownloadVersion.text(i18n.tr('Скачать'));
        buttonDownloadVersion.on('click', e => {
          e.preventDefault();
          e.target.blur();
          UTILS.fileDownload(`${fullName}.asfdocx`, item.identifier);
        });
        lastTd.append(buttonDownloadVersion);

        tr.append(lastTd);
      });
    }

    return table;
  }

  async getContentVersionsFile() {
    const container = $('<div>', {class: 'wf-versions-container'});
    const content = $('<div>', {class: 'wf-versions-content'});
    const button = $('<button>', {class: 'uk-button uk-button-default button-switch wf-button-version'});

    button.text(i18n.tr('Версии'));
    container.append(button, content);

    const table = await this.getFileVersions();
    content.append(table);

    return {container, button, content};
  }

  renderResolutions(){
    const {systemSettings} = Cons.getAppStore();
    const {docflow_resolution_template} = systemSettings;
    const {resolutions} = this._doc;
    const {resolutionsContainer} = this._doc.panels;

    resolutions.forEach(resolution => {
      const {items, author, canEdit} = resolution;
      if(items.length) {
        const container = $('<div>', {class: 'arm-resolution-container uk-position-relative uk-visible-toggle'});

        if(canEdit == "true") {
          const panelAction = $('<div>', {class: 'uk-hidden-hover', style: 'top: 15px; right: 15px; position: absolute;'});
          const editResolutionButton = $('<a href="#" uk-icon="icon: pencil" class="uk-icon">');

          panelAction.append(editResolutionButton);
          container.append(panelAction, `<span class="uk-text-bold uk-text-small">${i18n.tr('Резолюция')}</span>`);

          editResolutionButton.on('click', e => {
            e.preventDefault();
            e.target.blur();
            new Resolution(this._doc);
          });
        } else {
          container.append(`<span class="uk-text-bold uk-text-small">${i18n.tr('Резолюция')}</span>`);
        }

        items.forEach(item => {
          const itemContainer = $('<div>', {class: 'arm-resolution-item-container uk-text-small'});
          const finishDate = AS.FORMS.DateUtils.formatDate(new Date(Number(item.finishdate.date)), AS.FORMS.DateUtils.DATE_FORMAT);
          let itemText = docflow_resolution_template;
          itemText = itemText.replaceAll('${resolution.assignee}', item.user);
          itemText = itemText.replaceAll('${resolution.coassignees.commas}', item.users.map(x => getUserFullName(x.user)).join(', '));
          itemText = itemText.replaceAll('${resolution.date}', `${i18n.tr('в срок до')} ${finishDate}`);
          itemText = itemText.replaceAll('${resolution.text}', item.name);
          itemText = itemText.replaceAll('\n', '<br>');

          itemContainer.append(itemText);
          container.append(itemContainer);
        });

        container.append(`<span class="uk-text-small">${getUserFullName(author)}</span>`);

        resolutionsContainer.append(container);
      }
    });
  }

  async renderWindow(){
    this.window = $('<div>', {class: 'arm-window-document'});
    if(this._doc.actionID) this.window.attr('actionid', this._doc.actionID);
    if(this._doc.documentID) this.window.attr('documentidentifier', this._doc.documentID);

    const isResolution = chekResolutionItem(this._doc);

    const header = $('<div>', {class: 'arm-header uk-modal-header'});
    const body = $('<div>', {class: 'arm-body'});
    const leftPanel = $('<div>', {class: 'arm-left-panel'});

    const content = $('<div>', {class: 'arm-content'});
    const formPanel = $('<div>', {class: 'arm-form-panel'});
    const panelActions = $('<div>', {class: 'arm-form-panel-actions'});
    const currentFormContainer = $('<div>', {class: 'arm-form-container file-view-panel active'});
    const attachmentViewContainer = $('<div>', {class: 'arm-attachment-container file-view-panel'});
    const rccContainer = $('<div>', {class: 'arm-rcc-container file-view-panel'});

    const buttonDocumentRCC = $('<div>', {class: 'uk-button uk-button-default button-switch fonts'});

    const buttonsHeader = $('<div>', {class: 'arm-header-buttons'});
    const minButton = $('<span class="arm-min-button uk-margin-small-right" uk-icon="chevron-down"></span>');
    const closeButton = $('<span class="arm-close-button" uk-icon="close"></span>');

    const panelButtons = $('<div>', {class: 'arm-form-panel-buttons'});
    const workName = $('<div>', {class: 'arm-work-name'});
    const mobileMenu = $('<div>', {class: 'arm-menu-mobile'});
    const commentsContainer = $('<div>', {class: 'arm-comments-container'});
    const resolutionsContainer = $('<div>', {class: 'arm-resolutions-container'});
    const attachmentContainer = $('<div>', {class: 'arm-attachment-container', style: 'overflow: hidden;'});

    const panelSwitchButtons = $('<div>', {class: 'arm-switch-buttons uk-flex-inline uk-flex-wrap uk-flex-left uk-flex-middle uk-flex-wrap-middle'});
    const buttonSwitchInfo = $('<div>', {class: 'uk-button uk-button-default button-switch fonts pressed'});
    const buttonSwitchComment = $('<div>', {class: 'uk-button uk-button-default button-switch fonts'});
    const buttonSwitchResolutions = $('<div>', {class: 'uk-button uk-button-default button-switch fonts', style: 'position: absolute; right: 10px;'});

    const panelInfo = $('<div>', {class: 'arm-left-panel_info'});
    const panelComments = $('<div>', {class: 'arm-left-panel_comments', style: 'display: none;'});
    const panelResolutions = $('<div>', {class: 'arm-left-panel_resolutions', style: 'display: none;'});

    const buttonSwitchLeftPanel = $('<div>', {class: 'button_switch_left_panel'});
    buttonSwitchLeftPanel.append(
      `<span class="switch-button-icon" uk-icon="icon: chevron-double-left;"></span>`,
      `<span class="switch-button-text">${i18n.tr('Свернуть')}</span>`
    );
    buttonSwitchLeftPanel.attr('uk-tooltip', `title: ${i18n.tr('Свернуть')}; duration: 300;`);

    buttonSwitchInfo.append(`<span uk-icon="icon: info;"></span>`);
    buttonSwitchComment.append(`<span uk-icon="icon: comment;"></span>`);
    buttonSwitchResolutions.append(`<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#666"><g><rect fill="none" height="24" width="24"></rect></g><g><g><path d="M4,16v6h16v-6c0-1.1-0.9-2-2-2H6C4.9,14,4,14.9,4,16z M18,18H6v-2h12V18z M12,2C9.24,2,7,4.24,7,7l5,7l5-7 C17,4.24,14.76,2,12,2z M12,11L9,7c0-1.66,1.34-3,3-3s3,1.34,3,3L12,11z"></path></g></g></svg>`);

    buttonDocumentRCC.text(i18n.tr('Карточка'))
    .css({
      "width": "calc(100% - 30px)",
      "border-radius": "3px",
      "transform": "translateX(15px)",
      "height": "30px",
      "margin": "10px 0",
      "line-height": "30px",
      "user-select": "none"
    });

    this._doc.panels = {
      workName,
      commentsContainer,
      attachmentContainer,
      resolutionsContainer,
      currentFormContainer,
      attachmentViewContainer,
      rccContainer,
      buttonDocumentRCC,
      panelInfo,
      panelButtons,
      panelActions,
      mobileMenu,
      formPanel,
      leftPanel,
      documentWindow: this.window,
      documentPanel: this.panel
    };

    if(this._doc.sendButtonActions && this._doc.sendButtonActions.length) {
      const sendMenuContainer = $('<div>', {class: 'arm-send_menu_container'});
      const dropdownButton = $(`<button class="uk-button uk-button-default uk-width-expand" type="button" style="border-radius: 3px;">${i18n.tr('Отправить')}</button>`);
      const dropdownMenu = $(`<div uk-dropdown="mode: click">`);
      const dropdownList = $('<div>', {class: 'uk-nav uk-dropdown-nav'});

      dropdownMenu.append(dropdownList);
      sendMenuContainer.append(dropdownButton, dropdownMenu);

      sendMenuContainer.css({
        "width": "100%",
        "padding": "0 15px"
      });

      this._doc.panels.dropdownList = dropdownList;

      panelInfo.append(workName, panelButtons, sendMenuContainer, buttonDocumentRCC, attachmentContainer);
    } else {
      panelInfo.append(workName, panelButtons, buttonDocumentRCC, attachmentContainer);
    }

    if(this._doc.rccVisible && this._doc.activePanel == 'rcc') {
      attachmentViewContainer.removeClass('active');
      currentFormContainer.removeClass('active');
      rccContainer.addClass('active');
      buttonDocumentRCC.addClass('pressed');
      new _RCC(this._doc.docInfo, this._doc.panels.rccContainer);
    }

    panelSwitchButtons.append(buttonSwitchInfo, buttonSwitchComment);
    panelComments.append(commentsContainer);
    leftPanel.append(panelSwitchButtons, panelInfo, panelComments, buttonSwitchLeftPanel);
    if(isResolution) {
      panelResolutions.append(resolutionsContainer);
      panelSwitchButtons.append(buttonSwitchResolutions);
      leftPanel.append(panelResolutions);

      this.renderResolutions();
    }

    if(this._doc.formPlayer) {
      const {container: footer, button: buttonVersion, content: contentVersion} = await this.getContentVersionsFile();
      const playerContainer = $('<div>');
      playerContainer.css({
        "height": "calc(100% - 40px)",
        "width": "100%",
        "overflow": "auto",
        "background": "#fff",
        "padding": "30px",
        "transition": "0.3s"
      });

      let panelVersion = false;
      buttonVersion.off().on('click', e => {
        e.preventDefault();
        e.target.blur();
        if(panelVersion) {
          playerContainer.css({"height": "calc(100% - 40px)"});
          footer.css({"height": "40px"});
          buttonVersion.removeClass('pressed');
          contentVersion.removeClass('open');
        } else {
          playerContainer.css({"height": "calc(100% - 250px)"});
          footer.css({"height": "250px"});
          buttonVersion.addClass('pressed');
          contentVersion.addClass('open');
        }
        panelVersion = !panelVersion;
      });

      playerContainer.append(this._doc.formPlayer.view.container);
      formPanel.append(playerContainer, footer);

      setTimeout(() => {
        initOpenFilesInForm(this._doc.formPlayer);

        if(this._doc.matchingParam) initMatching(this._doc);
      }, 1000);
    }

    content.append(currentFormContainer, attachmentViewContainer, rccContainer);
    currentFormContainer.append(panelActions, formPanel);

    buttonsHeader.append(minButton, closeButton);
    header.append(`<h3 style="overflow: hidden; white-space: nowrap; width: calc(100% - 80px); margin: 0; font-size: 1.1em; position: absolute; top: 7px;">${this._doc.formName}</h3>`, buttonsHeader);

    const storageKey = `arm_window_param_${AS.OPTIONS.currentUser.userid}`;
    let leftPanelHide = false;
    let saveParam = localStorage.getItem(storageKey);
    if(saveParam) {
      saveParam = JSON.parse(saveParam);
      leftPanelHide = saveParam.leftPanelHide;
      if(leftPanelHide) {
        body.addClass('hide_left_panel');
        buttonSwitchLeftPanel.find('.switch-button-icon').attr("uk-icon", "icon: chevron-double-right;");
        buttonSwitchLeftPanel.find('.switch-button-text').text('');
        buttonSwitchLeftPanel.attr('uk-tooltip', `title: ${i18n.tr('Развернуть')}; duration: 300;`);
      }
    }

    buttonSwitchLeftPanel.on('click', e => {
      if(!leftPanelHide) {
        body.addClass('hide_left_panel');
        buttonSwitchLeftPanel.find('.switch-button-icon').attr("uk-icon", "icon: chevron-double-right;");
        buttonSwitchLeftPanel.find('.switch-button-text').text('');
        buttonSwitchLeftPanel.attr('uk-tooltip', `title: ${i18n.tr('Развернуть')}; duration: 300;`);
      } else {
        body.removeClass('hide_left_panel');
        buttonSwitchLeftPanel.find('.switch-button-icon').attr("uk-icon", "icon: chevron-double-left;");
        buttonSwitchLeftPanel.find('.switch-button-text').text(i18n.tr('Свернуть'));
        buttonSwitchLeftPanel.attr('uk-tooltip', `title: ${i18n.tr('Свернуть')}; duration: 300;`);
      }
      leftPanelHide = !leftPanelHide;
      localStorage.setItem(storageKey, JSON.stringify({
        leftPanelHide: leftPanelHide
      }));
    });

    body.append(leftPanel, content);
    this.window.append(header, body, mobileMenu);
    $('body').append(this.window);

    minButton.on('click', e => this.hideShowDocument());

    closeButton.on('click', e => {
      checkSavedForm(this._doc, () => {
        closeDocument(this._doc);
      });
    });

    buttonSwitchInfo.on('click', e => {
      e.preventDefault();
      e.target.blur();
      buttonSwitchComment.removeClass('pressed');
      buttonSwitchInfo.addClass('pressed');
      buttonSwitchResolutions.removeClass('pressed');
      panelComments.hide();
      panelResolutions.hide();
      panelInfo.fadeIn();
    });

    buttonSwitchComment.on('click', e => {
      e.preventDefault();
      e.target.blur();
      buttonSwitchInfo.removeClass('pressed');
      buttonSwitchComment.addClass('pressed');
      buttonSwitchResolutions.removeClass('pressed');
      panelInfo.hide();
      panelResolutions.hide();
      panelComments.fadeIn();
    });

    buttonSwitchResolutions.on('click', e => {
      e.preventDefault();
      e.target.blur();
      buttonSwitchInfo.removeClass('pressed');
      buttonSwitchComment.removeClass('pressed');
      buttonSwitchResolutions.addClass('pressed');
      panelInfo.hide();
      panelComments.hide();
      panelResolutions.fadeIn();
    });

    new ARMDocumentButtons(this._doc);
  }

  openDocument(){
    this.window.fadeIn(200);
    this.state = 'open';
    $('.arm-window-document').attr('arm-active-window', null);
    this.window.attr('arm-active-window', true).attr('state', this.state);
    $('.footer-document').removeClass('arm-active-panel');
    this.panel.addClass('arm-active-panel');
    if(this._doc.type == 'work') {
      history.replaceState(null, null, `/${this._doc.pathname}/?actionID=${this._doc.actionID}`);
    } else {
      history.replaceState(null, null, `/${this._doc.pathname}/?document_identifier=${this._doc.documentID}`);
    }
  }

  hideShowDocument(){
    if(!this.window.attr('arm-active-window')) {
      this.openDocument();
    } else {
      if(this.state == 'open') {
        this.state = 'hide';
        this.panel.removeClass('arm-active-panel');
        this.window.fadeOut(200).attr('arm-active-window', null).attr('state', this.state);

        let aw = $('.arm-window-document[state="open"]');
        if(aw.length) {
          aw = $(aw[0]);
          aw.attr('arm-active-window', true);

          const actionID = aw.attr('actionid');
          const docID = aw.attr('documentidentifier');

          if(actionID) {
            $(`.footer-document[actionid="${actionID}"]`).addClass('arm-active-panel');
            history.replaceState(null, null, `/${this._doc.pathname}/?actionID=${actionID}`);
          } else {
            $(`.footer-document[documentidentifier="${docID}"]`).addClass('arm-active-panel');
            history.replaceState(null, null, `/${this._doc.pathname}/?document_identifier=${docID}`);
          }

        } else {
          history.replaceState(null, null, `/${this._doc.pathname}`);
        }
      } else {
        this.openDocument();
      }
    }
  }

  addAttacmentListener(){
    const {
      attachmentContainer,
      currentFormContainer,
      attachmentViewContainer,
      rccContainer,
      buttonDocumentRCC
    } = this._doc.panels;

    attachmentContainer.on('file_dbl_click file_context_open', async e => {
      const {name, uuid, dataUUID, is_editable, mobile} = e.eventParam;

      this._doc.rccVisible = false;
      buttonDocumentRCC.removeClass('pressed');

      if(dataUUID) {
        this._doc.activePanel = 'form';
        attachmentViewContainer.removeClass('active');
        rccContainer.removeClass('active');
        currentFormContainer.addClass('active');
        if(this._doc.formPlayer && dataUUID != this.dataUUID) {
          this._doc.formPlayer.showFormData(null, null, dataUUID);
        }
      } else {
        this._doc.activePanel = 'file';
        attachmentViewContainer.empty();
        currentFormContainer.removeClass('active');
        rccContainer.removeClass('active');
        attachmentViewContainer.addClass('active');
        const file = new AttachmentFile(name, uuid, attachmentViewContainer);
        file.open();
      }
    });
  }

  async init(){
    this.documentName = this._doc.documentName;
    this.matchingParam = this._doc.matchingParam || null;

    if(this._doc.formPlayer) {
      this._doc.formPlayer.view.setEditable(this._doc?.editable || false);
      this._doc.formPlayer.showFormData(null, null, this._doc.dataUUID);
      if($(document).width() < 769) this._doc.formPlayer.model.showView('mobile');
    }

    if(!this.window) await this.renderWindow();

    this.openDocument();

    this.panel.on('click', e => {
      this.hideShowDocument();
    });

    this.window.on('show-document', e => {
      this.hideShowDocument();
    });

    this.window.on('hide-window', e => {
      this.window.hide();
      this.state = 'hide';
      this.window.attr('arm-active-window', null).attr('state', this.state);
      this.panel.removeClass('arm-active-panel');
    });

    if(this._doc.workInfo) {
      const {actionID, is_new} = this._doc.workInfo;
      if(is_new && is_new == "true") {
        AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/workflow/work/set_seen?workID=${actionID}`);
      }

      new DocumentComments(this._doc.documentID, actionID, this._doc.panels.commentsContainer);
    } else {
      new DocumentComments(this._doc.documentID, null, this._doc.panels.commentsContainer);
    }

    new DocumentAttachments(this._doc.documentID, this._doc.panels.attachmentContainer);

    this.addAttacmentListener();
  }
}

class ARMFooter {
  constructor() {
    this.footer = null;
    this.init();
  }

  async initParams(_doc){
    Cons.showLoader();
    try {
      if(_doc.type == 'work') {
        _doc.documentID = await appAPI.getWorkDocument(_doc.actionID);
        if(!_doc.hasOwnProperty('workInfo')) {
          _doc.workInfo = await appAPI.getWorkInfo(_doc.actionID);
          if(_doc.workInfo && _doc.documentID) _doc.workInfo.documentID = _doc.documentID;
        }
      }

      _doc.docInfo = await appAPI.getDocumentInfo(_doc.documentID);
      if(!_doc.docInfo) throw new Error('Ошибка получения информации по документу');
      if(_doc.docInfo.hasOwnProperty('errorCode') && _doc.docInfo.errorCode != '0') throw new Error(_doc.docInfo.errorMessage);

      _doc.process = await AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/workflow/get_execution_process?documentID=${_doc.documentID}&locale=${AS.OPTIONS.locale}`);
      _doc.processResponsible = getResponsibleUserWork(_doc.process);
      _doc.process = getUserWork(_doc.process, AS.OPTIONS.currentUser.userid);

      if(_doc.type == 'document') {
        if(_doc.process.length) {
          let actionID;
          const currentUserWork = _doc.process.find(x => x.responsibleUserID == AS.OPTIONS.currentUser.userid);
          if(currentUserWork) {
            actionID = currentUserWork.actionID;
          } else {
            actionID = _doc.process[_doc.process.length - 1].actionID;
          }
          _doc.workInfo = await appAPI.getWorkInfo(actionID);
          if(_doc.workInfo) _doc.workInfo.documentID = _doc.documentID;
        }
      }

      if(_doc.type == 'work' || _doc.hasOwnProperty('workInfo')) {
        _doc.docActions = await appAPI.getWorkActions(_doc.workInfo.actionID);
      } else {
        _doc.docActions = await AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/docflow/document_actions?documentID=${_doc.documentID}&locale=${AS.OPTIONS.locale}`);
      }

      _doc.sendButtonActions = _doc.docActions.filter(x => ['TRANSMIT', 'REASSIGN', 'SEND'].includes(x.action));
      _doc.resolution = _doc.docActions.find(x => ['RESOLUTION'].includes(x.action));

      _doc.dataUUID = _doc.docInfo?.asfDataID || null;
      _doc.mainDataUUID = _doc.dataUUID;

      if(_doc.dataUUID) {
        _doc.registryInfo = await appAPI.getRegistryInfoByID(_doc.docInfo.registryID);

        _doc.registryInfo = await appAPI.getRegistryInfoByID(_doc.docInfo.registryID);
        const msgErrorRead = 'Вам запрещен доступ к этому документу';
        if(!_doc.registryInfo) throw new Error(msgErrorRead);
        if(_doc.registryInfo.hasOwnProperty('rights') && _doc.registryInfo.rights == "no") throw new Error(msgErrorRead);
        if(_doc.registryInfo.rr_read != "Y") throw new Error(msgErrorRead);

        _doc.form = await AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/asforms/form/${_doc.docInfo.formID}?locale=${AS.OPTIONS.locale}`);

        _doc.formName = _doc.form.name;
        _doc.registryCode = _doc.registryInfo.code;
        _doc.meaning = await appAPI.getDocMeaningContent(_doc.dataUUID);
        if(_doc.workInfo) _doc.workInfo.dataUUID = _doc.dataUUID;

        _doc.formPlayer = AS.FORMS.createPlayer();

        _doc.documentName = _doc.meaning || _doc.formName;

        _doc.activePanel = 'form';
        _doc.rccVisible = false;
      } else {
        if(_doc.workInfo) _doc.documentName = _doc.workInfo.name;

        _doc.activePanel = 'rcc';
        _doc.rccVisible = true;
      }

      if(_doc.workInfo && _doc.workInfo.completionFormID && _doc.workInfo.completionFormID != "") {
        _doc.workInfo.completionForm = await appAPI.getCompletionForm(_doc.workInfo.completionFormID);
      }

      const param = {};
      if(_doc.hasOwnProperty('documentID')) param.documentID = _doc.documentID;
      if(_doc.hasOwnProperty('actionID')) param.actionID = _doc.actionID;
      _doc.resolutions = await appAPI.resolution.get(param);

      _doc.pathname = `${window.location.pathname.replaceAll('/', '')}`;

      Cons.hideLoader();

      this.renderDocToFooter(_doc);
    } catch (err) {
      Cons.hideLoader();
      console.log('ERROR ARMDocument: ', err.message);
      showMessage(i18n.tr(err.message), 'error');
      history.replaceState(null, null, `/${window.location.pathname.replaceAll('/', '')}`);
    }
  }

  renderDocToFooter(_doc){
    const panel = $('<div>', {class: 'footer-document'})
    .attr('uk-tooltip', `title: ${_doc.documentName}; duration: 300;`)
    .html(`<span uk-icon="icon: file-text"></span> ${_doc.documentName}`);

    if(_doc.actionID) panel.attr('actionid', _doc.actionID);
    if(_doc.documentID) panel.attr('documentidentifier', _doc.documentID);

    if(!this.footer) this.renderPanel();

    this.footer.append(panel);
    new ARMDocument(panel, _doc);
  }

  async openDocument(param){
    try {
      const _doc = new DocumentParams(param);
      if(!_doc.hasOwnProperty('type')) throw new Error('Не удалось открыть документ. Не передан параметр type');

      if(_doc.type == 'work' && !_doc.hasOwnProperty('actionID')) throw new Error('Не удалось открыть документ. Не передан параметр actionID');

      if(_doc.type == 'document' && !_doc.hasOwnProperty('documentID')) throw new Error('Не удалось открыть документ. Не передан параметр documentID');

      _doc.editable = _doc?.editable || false;

      const {openDocsWindow = []} = Cons.getAppStore();
      let doc = null;
      if(_doc.type == 'document') {
        doc = openDocsWindow.find(x => x.documentID === _doc.documentID);
      } else {
        doc = openDocsWindow.find(x => x.actionID === _doc.actionID);
      }

      if(!doc) {
        await this.initParams(_doc);
        openDocsWindow.push(_doc);
        Cons.setAppStore({openDocsWindow: openDocsWindow});
      } else {
        if(_doc.type == 'document') {
          $(`.arm-window-document[documentidentifier="${_doc.documentID}"]`).trigger('show-document');
        } else {
          $(`.arm-window-document[actionid="${_doc.actionID}"]`).trigger('show-document');
        }
      }

    } catch (err) {
      console.log('ERROR ARMDocument: ', err.message);
      showMessage(i18n.tr(err.message), 'error');
      history.replaceState(null, null, `/${window.location.pathname.replaceAll('/', '')}`);
    }

  }

  initListener(){
    if(Cons.getAppStore().open_document_listener) return;

    if(Cons.getCurrentPage().code == 'listWorksPage') {
      addListener('custom_open_document', 'root-panel', event => this.openDocument(event));
      Cons.setAppStore({open_document_listener: true});
    };

    $('#root-panel').off().on('custom_open_document', e => {
      if(e.hasOwnProperty('eventParam')) this.openDocument(e.eventParam);
    });
  }

  renderPanel() {
    const {code} = Cons.getCurrentPage();
    if(['auth_page', 'authPage', 'start_page'].includes(code)) return;

    if($('.footer-panel').length) {
      this.footer = $('.footer-panel');
    } else {
      this.footer = $('<div>', {class: 'footer-panel'});
      const homeButton = $('<span class="uk-margin-small-right arm-home-button" uk-icon="icon: home; ratio: 1.5"></span>');

      homeButton.on('click', e => $('.arm-window-document').trigger('hide-window'));
      this.footer.append(homeButton);
    }

    $('#root-panel').append(this.footer);
  }

  init(){
    this.renderPanel();
    this.initListener();
  }
}

new ARMFooter();

$(document).mouseup(event => {
	setTimeout(() => {
		AS.FORMS.popupPanel.hide();
	}, 0);
}).click(event => {
	AS.FORMS.popupPanel.hide();
  $('.workflow-context-menu').remove();
}).on('contextmenu', () => $('.workflow-context-menu').remove());
