const getRccInfoContent = (docRCC, docInfo, doctypes, notEditable) => {
  const rccInfoContent = $('<div>');

  const {container: docNameContainer, textarea: docNameInput} = Components.createInputTextArea(i18n.tr("Кр. содерж."));
  docNameInput.val(docRCC.content);
  rccInfoContent.append(docNameContainer);

  const regData = $('<div uk-grid style="align-items: baseline; margin-top: 0;">');
  rccInfoContent.append(regData);

  const {container: docNumberContainer, input: docNumberInput} = Components.createInputText(i18n.tr("Номер"));
  docNumberInput.val(docRCC.number);
  docNumberInput.css('min-width', '290px');
  regData.append(docNumberContainer);

  const {container: docRegDateContainer, dateTimeInput: docRegDateInput} = Components.createDateTimeInput(i18n.tr("Дата регистрации"), docInfo.regDate || '');
  regData.append(docRegDateContainer);
  docRegDateContainer.find('.uk-form-controls').css('display', 'flex');

  const docTypeData = $('<div uk-grid style="align-items: baseline; margin-top: 0;">');
  rccInfoContent.append(docTypeData);

  const docTypeItems = doctypes.map(x => ({label: x.name, value: x.code}));
  const {container: docTypeContainer, select: docTypeSelect} = Components.createSelectComponent(i18n.tr("Тип документа"), docTypeItems);
  docTypeSelect.val(docRCC.docTypeCode);
  docTypeData.append(docTypeContainer);
  if(notEditable) docTypeSelect.attr('disabled', true);

  const {container: durationContainer, input: durationInput} = Components.createInputNumber(i18n.tr("Длительность (раб.дн)"));
  durationInput.val(docRCC.length || '1');
  docTypeData.append(durationContainer);

  const {container: correspondentOrgContainer, input: correspondentOrgInput} = Components.createInputText(i18n.tr("Корреспондент (орг)"));
  correspondentOrgInput.val(docInfo.correspondentOrg);
  rccInfoContent.append(correspondentOrgContainer);

  const {container: correspondentContainer, input: correspondentInput} = Components.createInputText(i18n.tr("Корреспондент"));
  correspondentInput.val(docInfo.correspondent);
  rccInfoContent.append(correspondentContainer);

  const outDocData = $('<div uk-grid style="align-items: baseline; margin-top: 0;">');
  rccInfoContent.append(outDocData);

  const {container: outDocNumberContainer, input: outDocNumberInput} = Components.createInputText(i18n.tr("Номер исх."));
  outDocNumberInput.css('min-width', '290px');
  outDocNumberInput.val(docRCC.numberOut || '');
  outDocData.append(outDocNumberContainer);

  const {container: outDocRegDateContainer, dateTimeInput: outDocRegDateInput} = Components.createDateTimeInput(i18n.tr("Дата исх."), docRCC.dateOut || '');
  outDocData.append(outDocRegDateContainer);
  outDocRegDateContainer.find('.uk-form-controls').css('display', 'flex');

  const inputs = {
    docNameInput,
    docNumberInput,
    docRegDateInput,
    docTypeSelect,
    durationInput,
    correspondentOrgInput,
    correspondentInput,
    outDocNumberInput,
    outDocRegDateInput
  }

  return {rccInfoContent, inputs};
}

const parseSignDate = date => {
	date = date.split(' ');
  return [date[1].replaceAll('.', ':'), date[0]].join(' ');
}

const signObjToArr = (data, fielsd) => {
  return data.map((x, i) => {
  	const tmp = [];
    fielsd.forEach(key =>
      key == 'index' ? tmp.push(String(i + 1)) : (key == 'signDate' ? tmp.push(parseSignDate(x[key])) : tmp.push(x[key]))
    );
    return tmp;
  });
}

const getSignListContent = list => {
  if(!list || !list.length) return null;

  const content = $('<div>');
  const headers = [i18n.tr('№ п/п'), i18n.tr('Фамилия И.О.'), i18n.tr('Должность'), i18n.tr('Дата'), i18n.tr('Тип подписи'), i18n.tr('Действие'), i18n.tr('Результат действия')];
  const rows = signObjToArr(list, ['index', 'userName', 'position', 'signDate', 'value', 'signType', 'actionResult']);
  const {table} = Components.createTable({headers, rows}, ['rcc-table', 'uk-table-small', 'uk-table-responsive']);
  content.append(table);
  return content;
}

const getOtherListContent = list => {
  if(!list || !list.length) return null;

  const content = $('<div>');
  const headers = [i18n.tr('№ п/п'), i18n.tr('Фамилия И.О.'), i18n.tr('Должность'), i18n.tr('Дата'), i18n.tr('Результат действия'), i18n.tr('Комментарий')];
  const rows = signObjToArr(list, ['index', 'userName', 'position', 'signDate', 'signResult', 'comment']);
  const {table} = Components.createTable({headers, rows}, ['rcc-table', 'uk-table-small', 'uk-table-responsive']);
  content.append(table);
  return content;
}

const getDocflowTable = htmlStr => {
  if(!htmlStr || htmlStr == '') return null;

  const docflowTable = $(htmlStr).find('.docflowTable');
  const docflowTableHeader = [...docflowTable.find('.docflowTableHeader')];

  docflowTableHeader.forEach(x => {
    const currentH = $(x).text().replaceAll('\n', '').trim();
    $(x).text(currentH);
  });

  docflowTable.addClass('uk-table uk-table-small uk-table-responsive rcc-table');

  return docflowTable;
}

const parseHistory = data => {
  const result = [];

  const getSpan = (text, started, isPadding) => {
    if(!text || text == '') return '';
    const span = $('<span>');
    span.text(text);
    if(!started) span.css('color', '#aaa');
    if(isPadding) span.css('padding-left', `${isPadding*15}px`);

    return span;
  }

  const isShow = ({ showInHistory, external }) => showInHistory || external;
  
  const f = (d, funcIndex) => {

    d.forEach((x, i) => {
      const t = [];
      const {name, started, finished, comment, userName, authorName, finishedUser, subProcesses} = x;
      if(isShow(x)) {
        t.push(getSpan(name, started, funcIndex));
        t.push(getSpan(userName, started));
        t.push(getSpan(authorName, started));
        t.push(getSpan(started ? AS.FORMS.DateUtils.formatDate(new Date(started), '${dd}.${mm}.${yy} ${HH}:${MM}') : '', started));
        t.push(getSpan(finished ? AS.FORMS.DateUtils.formatDate(new Date(finished), '${dd}.${mm}.${yy} ${HH}:${MM}') : '', started));
        t.push(getSpan(finishedUser, started));
        t.push(getSpan(comment, started));
        result.push(t);

        if(subProcesses && subProcesses.length) f(subProcesses, funcIndex + 1);
      }
    });
  }

  f(data, 0);
  return result;
}

const parseChanges = data => {
  const result = [];

  const getDescription = item => {
    const {description, actionID, actionName, userName, fileName, folderName} = item;
    const tmp = {
      2: i18n.tr('{0} добавил в папку "{1}" файл "{2}"'),
      4: i18n.tr('{0} удалил из папки "{1}" файл "{2}"'),
      16: i18n.tr('{0} изменил в папке "{1}" файл "{2}"')
    };

    if(actionID) {
      if(tmp.hasOwnProperty(actionID)) {
        return tmp[actionID].replace('{0}', userName).replace('{1}', folderName).replace('{2}', fileName);
      } else {
        return '';
      }
    } else {
      return description.replaceAll('\n', '<br>');
    }
  }

  data.forEach((item, i) => {
    const {host, userName, date, comment} = item;
    const t = [];
    t.push(`${i+1}.`);
    t.push(userName || '');
    t.push(date ? UTILS.customFormatDate(UTILS.formatDate(new Date(date), true)) : '');
    t.push(host || '');
    t.push(getDescription(item));
    t.push(i18n.tr(comment) || '');
    result.push(t);
  });

  return result;
}

const parseChildDocuments = async (childDocuments, parentDocID) => {
  const result = [];

  if(childDocuments && childDocuments.length) {
    for(let i = 0; i < childDocuments.length; i++) {
      const {author, number, name, documentID, regDate} = childDocuments[i];
      const {docTypeName} = await appAPI.getDocumentRCC(documentID);

      const deleteButton = $(`<a href="javascript:void(0);" uk-icon="trash"></a>`);

      deleteButton.on('click', async e => {
        const msgConfirm = i18n.tr("Вы действительно хотите удалить связь с дочерним документом?");

        UIkit.modal.confirm(msgConfirm, {labels: {ok: i18n.tr('Да'), cancel: i18n.tr('Отмена')}})
        .then(async () => {
          const deleteResult = await appAPI.deleteChildDocument(parentDocID, documentID);
          if(deleteResult && deleteResult.errorCode == 0) {
            $(deleteButton).parent().parent().remove();
            showMessage(i18n.tr(deleteResult.errorMessage), 'success');
          } else {
            showMessage(i18n.tr('Произошла ошибка при удалении дочернего документа'), 'error');
          }
        }, () => {
          return;
        });
      });

      const t = [
        author,
        number,
        name,
        docTypeName || "",
        AS.FORMS.DateUtils.formatDate(new Date(regDate), '${dd}.${mm}.${yyyy}'),
        deleteButton,
        {documentID}
      ];

      result.push(t);
    }
  }

  return result;
}

const renderKeyInfo = async (eventClick, certID, documentID) => {
  const signinfo = await appAPI.testSigns(certID, documentID);
  const allInfoCert = JSON.parse(signinfo.allInfoCert);
  const content = $('<div>', {class: 'key-info-overlay'});
  const dialog = $('<div>', {class: 'key-info-dialog'});
  const table = $('<table>', {style: "font-size: small;"});
  const tBody = $('<tbody>');

  for (const key in allInfoCert) {
    if (key != "CERT") {
      const keyTd = $("<td align='right' style='margin: 2px; padding: 6px; font-weight: bold'>").text(key.replace(/KEY_/g,""));
      const valueTd = $("<td style='padding: 6px'>").text(allInfoCert[key]);
      tBody.append($("<tr>").append(keyTd, valueTd));
    }
  }

  content.on('click', e => {
    if($(e.target).hasClass('key-info-overlay')) content.remove();
  });

  content.css({
    'position': 'absolute',
    'left': '0',
    'top': '0',
    'width': '100%',
    'height': '100vh',
    'z-index': '1000'
  });

  dialog.css({
    'position': 'relative',
    'left': `${eventClick.clientX + eventClick.offsetX}px`,
    'top': `${eventClick.clientY + eventClick.offsetY}px`,
    'width': 'max-content',
    'max-width': '600px',
    'height': 'auto',
    'border': '1px solid #C3D9FF',
    'background': '#fff'
  });

  table.append(tBody);
  dialog.append(table);
  content.append(dialog);

  $('body').append(content);
}

const parseSignList = (documentID, data) => {
  const result = [];

  data.forEach((item, i) => {
    const t = [];

    let keyExpiryDate = item.keyExpiryDate.split('.');
    keyExpiryDate = `${keyExpiryDate[1]}-${keyExpiryDate[0]}-${keyExpiryDate[2]}`;
    keyExpiryDate = new Date(keyExpiryDate) > new Date();

    const button = $(`<a href="" uk-icon="icon: info" style="width: 40px;"></a>`);
    const span = $('<span>', {style: "display: flex; justify-content: space-between;"});
    span.append(item.nameOgrInfo, button);

    button.on('click', e => {
      e.preventDefault();
      renderKeyInfo(e, item.certID, documentID);
    });

    const fieldKeyExpiryDate = $('<span>');
    if(keyExpiryDate) {
      fieldKeyExpiryDate.text(i18n.tr('Подпись верна'));
      fieldKeyExpiryDate.css('color', 'rgb(12, 213, 112)');
    } else {
      fieldKeyExpiryDate.text(i18n.tr('Публичный ключ устарел'));
      fieldKeyExpiryDate.css('color', 'rgb(222, 225, 8)');
    }

    t.push(item.name);
    t.push(item.date);
    t.push(span);
    t.push(`${item.keyReleaseDate} - ${item.keyExpiryDate}`);
    t.push(fieldKeyExpiryDate);

    result.push(t);
  });

  return result;
}

const getSignListTable = (documentID, data) => {
  if(!data || !data.length) return null;
  const content = $('<div>');
  const headers = [i18n.tr('ФИО подписавшего'), i18n.tr('Дата подписи'), i18n.tr('Имя, организация на сертификате'), i18n.tr('Срок действия сертификата'), i18n.tr('Результат проверки')];
  const rows = parseSignList(documentID, data);
  const {table} = Components.createTable({headers, rows}, ['rcc-table', 'uk-table-small', 'uk-table-responsive']);
  content.append(table);
  return content;
}

const getDocHistoryTable = data => {
  if(!data || !data.length) return null;
  const content = $('<div>');
  const headers = [i18n.tr('Название'), i18n.tr('Ответственный'), i18n.tr('Автор'), i18n.tr('Дата начала'), i18n.tr('Дата завершения'), i18n.tr('Завершил'), i18n.tr('Комментарий')];
  const rows = parseHistory(data);
  const {table} = Components.createTable({headers, rows}, ['rcc-table', 'uk-table-small', 'uk-table-responsive']);
  content.append(table);
  return content;
}

const getDocChangesTable = data => {
  if(!data || !data.length) return null;
  const content = $('<div>');
  const headers = [i18n.tr('№'), i18n.tr('Пользователь'), i18n.tr('Дата'), i18n.tr('IP-адрес'), i18n.tr('Описание'), i18n.tr('Комментарий')];
  const rows = parseChanges(data);
  const {table} = Components.createTable({headers, rows}, ['rcc-table', 'uk-table-small', 'uk-table-responsive']);
  content.append(table);
  return content;
}

const createChildDocumentsTable = (data, classes = []) => {
  const {headers, rows} = data;
  const container = $('<div>');
  const table = $('<table>', {class: "uk-table"});
  const thead = $('<thead>');
  const tbody = $('<tbody>');
  const theadTr = $('<tr>');

  classes.forEach(addClass => table.addClass(addClass));

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

  rows.forEach(row => {
    const tr = $('<tr>');
    tbody.append(tr);
    row.forEach(text => {
      if(typeof text == 'object' && text.hasOwnProperty('documentID')) {
        tr.on('dblclick', e => {
          if(e.target.nodeName !== 'TD') return;

          const eventParam = {
            type: 'document',
            documentID: text.documentID
          };
          $('#root-panel').trigger({type: 'custom_open_document', eventParam});
        });
      } else {
        const td = $('<td>');
        td.html(text);
        tr.append(td);
      }
    });
  });

  thead.append(theadTr);
  table.append(thead).append(tbody);
  container.append(table);

  return {container, table};
}

const getChildDocumentsContent = async (childDocuments, parentDocID) => {
  const content = $('<div>');
  const headers = [i18n.tr('Автор'), i18n.tr('Номер'), i18n.tr('Кр. содерж.'), i18n.tr('Тип документа'), i18n.tr('Дата регистрации'), ''];
  const rows = await parseChildDocuments(childDocuments, parentDocID);
  const {table} = createChildDocumentsTable({headers, rows}, ['rcc-table', 'uk-table-small', 'uk-table-responsive']);
  content.append(table);
  return content;
}

this._RCC = class {

  constructor(docInfo, parentContainer, notEditable = false){
    this.docInfo = docInfo;
    this.parentContainer = parentContainer;
    this.notEditable = notEditable;

    this.documentID = null;
    this.doctypes = null;
    this.docRCC = null;
    this.signList = {};
    this.documentHistory = null;
    this.docChanges = null;
    this.childDocuments = null;

    this.init();
  }

  initSaveRCC(inputs) {
    const getDateTime = dt => $(dt[0]).val() != '' ? `${$(dt[0]).val()}`.trim() : '';

    const {
      docNameInput,
      docNumberInput,
      docRegDateInput,
      docTypeSelect,
      durationInput,
      correspondentOrgInput,
      correspondentInput,
      outDocNumberInput,
      outDocRegDateInput
    } = inputs;

    this.buttonSaveRCC.on('click', e => {
      Cons.showLoader();

      const rccData = {};
      rccData.documentID = this.documentID;
      rccData.subject = docNameInput.val();
      rccData.number = docNumberInput.val();
      rccData.reg_date = getDateTime(docRegDateInput);
      rccData.doc_type = docTypeSelect.val();
      rccData.duration = durationInput.val();
      rccData.correspondent_org = correspondentOrgInput.val();
      rccData.correspondent = correspondentInput.val();
      rccData.base_number = outDocNumberInput.val();
      rccData.base_date = getDateTime(outDocRegDateInput);
      rccData.base = this.docRCC.bases;

      if(!rccData.doc_type) {
        showMessage(i18n.tr('Выберите тип документа. Если список пуст, то обратитесь к разработчику Synergy.'), 'error');
        Cons.hideLoader();
        return;
      }

      appAPI.saveRCC(rccData).then(res => {
        Cons.hideLoader();
        if(res && res.errorCode == 0) {
          showMessage(i18n.tr('Документ сохранен'), 'success');
        } else {
          showMessage(i18n.tr('Ошибка сохранения РКК'), 'error');
        }
      });

    });
  }

  checkEDSSigns(){
    const content = getSignListTable(this.documentID, this.signList.formPlayerSigns);
    $(content).dialog({
      modal: true,
      width: 850,
      height: 500,
      resizable: true,
      title: i18n.tr("Проверить ЭЦП"),
      show: {effect: 'fade', duration: 500},
      hide: {effect: 'fade', duration: 500},
      close: function() {
        $(this).remove();
      }
    });
  }

  async render() {
    const rccContainer = $('<div>', {class: 'rcc_container'});
    const rccData = $('<div>', {class: 'rcc_data'});
    const panelRccButtons = $('<div>', {class: 'rcc_buttons'});

    this.buttonSaveRCC = $('<div>', {id: 'buttonSaveRCC', title: i18n.tr("Сохранить")});
    this.buttonSaveRCC.append('<span class="material-icons">save</span>');

    if(!this.notEditable) {
      panelRccButtons.append(this.buttonSaveRCC);
      rccContainer.append(panelRccButtons, rccData);
    } else {
      rccContainer.append(rccData);
      rccData.addClass('no_rcc_buttons');
    }
    this.parentContainer.empty().append(rccContainer);

    const accordionItems = [];

    //осноная информация по РКК
    const {rccInfoContent, inputs} = getRccInfoContent(this.docRCC, this.docInfo, this.doctypes, this.notEditable);
    if(rccInfoContent) {
      accordionItems.push({
        title: i18n.tr("РКК"),
        content: rccInfoContent,
        open: true
      });
      this.initSaveRCC(inputs);
    }

    //ход выполнения
    const historyTable = getDocHistoryTable(this.documentHistory);
    if(historyTable) accordionItems.push({
      title: i18n.tr("Ход выполнения"),
      content: historyTable
    });

    //Изменения в документе
    const changesTable = getDocChangesTable(this.docChanges);
    if(changesTable) accordionItems.push({
      title: i18n.tr("Изменения в документе"),
      content: changesTable
    });

    // подписи
    const signListContent = getSignListContent(this.signList.signs);
    if(signListContent) {
      accordionItems.push({
        title: i18n.tr("Лист подписей"),
        content: signListContent
      });
      if(this.signList.hasOwnProperty('formPlayerSigns') && this.signList.formPlayerSigns && this.signList.formPlayerSigns.length) {
        const checkSignButton = $('<button>', {class: "uk-button uk-button-default uk-button-small"});
        checkSignButton.text(i18n.tr('Проверить ЭЦП'));
        signListContent.prepend(checkSignButton);
        checkSignButton.on('click', e => {
          this.checkEDSSigns();
        });
      }
    }

    // утверждения
    const approvalListContent = getOtherListContent(this.signList.approval);
    if(approvalListContent) accordionItems.push({
      title: i18n.tr("Лист утверждения"),
      content: approvalListContent
    });

    // согласования
    const agreementListContent = getOtherListContent(this.signList.agreement);
    if(agreementListContent) accordionItems.push({
      title: i18n.tr("Лист согласования"),
      content: agreementListContent
    });

    // ознакомления
    const acquaintanceListContent = getOtherListContent(this.signList.acquaintance);
    if(acquaintanceListContent) accordionItems.push({
      title: i18n.tr("Лист ознакомления"),
      content: acquaintanceListContent
    });

    // Дочерние документы
    const childDocumentsContent = await getChildDocumentsContent(this.childDocuments, this.documentID);
    if(childDocumentsContent) accordionItems.push({
      title: i18n.tr("Дочерние документы"),
      content: childDocumentsContent
    });

    const accordion = Components.createAccordion(accordionItems, 'rcc-accordion');

    rccData.append(accordion);
  }

  async init(){
    Cons.showLoader();
    this.parentContainer.empty();

    try {
      this.documentID = this.docInfo.documentID;
      this.doctypes = await appAPI.getDoctypes();
      this.docRCC = await appAPI.getDocumentRCC(this.documentID);
      this.documentHistory = await appAPI.getDocumentHistory(this.documentID); //ход выполнения
      this.docChanges = await appAPI.getDocChanges(this.documentID); //Изменения в документе
      this.childDocuments = await appAPI.getChildDocuments(this.documentID); // Дочерние документы

      this.signList.signs = await appAPI.getSignListXML(this.documentID, -1); // подписи
      this.signList.approval = await appAPI.getSignListXML(this.documentID, 1); // утверждения
      this.signList.agreement = await appAPI.getSignListXML(this.documentID, 0); // согласования
      this.signList.acquaintance = await appAPI.getSignListXML(this.documentID, 2); // ознакомления

      if(this.docInfo.asfDataID) {
        this.signList.formPlayerSigns = await appAPI.formPlayerGetSigns(this.docInfo.asfDataID, -1); // подписи
      }

      this.render();
      Cons.hideLoader();
    } catch (err) {
      Cons.hideLoader();
      console.log('ERROR _RCC: ', err.message);
      showMessage(i18n.tr(err.message), 'error');
    }
  }
}
