const compContainer = $(`#${comp.code}`);
const boardContent = compContainer.find('.kanban-board-content');

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

const KanbanBoard = {
  registryCode: null,
  registryID: null,
  registryName: '',
  rights: [],
  filterCode: null,
  formCode: null,
  formId: null,
  formName: '',
  statusDict: null,
  fields: null,
  fieldDict: null,
  countInPart: 5,

  columns: [],
  searchString: null,
  filterSearchUrl: null,
  sum: null,
  pageCode: null,

  stringLength: 50,

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

  getUrlParam: function(column) {
    const {key, currentPage, countInPart} = column;
    let param = `?registryCode=${this.registryCode}`;
    if(this.filterCode) param += `&filterCode=${this.filterCode}`;
    if(this.fields && this.fields.length > 0) {
      this.fields.forEach(x => param += `&fields=${x.code}`);
      param+=`&fields=${this.fieldDict}`;
    }
    if(this.searchString) param += `&searchString=${this.searchString}`;

    if(this.filterSearchUrl) {
      param += this.filterSearchUrl;
      if(key) {
        let next = this.getNextFieldNumber(this.filterSearchUrl);
        param += `&field${next}=${this.fieldDict}&condition${next}=TEXT_EQUALS&key${next}=${key}`;
      }
    } else {
      if(key) param += `&field=${this.fieldDict}&condition=TEXT_EQUALS&key=${key}`;
    }

    param += `&pageNumber=${currentPage}&countInPart=${countInPart}`;
    return param;
  },

  searchInRegistry: async function(param){
    return new Promise(resolve => {
      rest.synergyGet(`api/registry/data_ext${param}`, resolve, err => {
        console.log(`KanbanBoard ERROR [ searchInRegistry ]: ${JSON.stringify(err)}`);
        resolve(null);
      });
    });
  },

  getSumRowInRegistry: async function(fieldCode, key){
    let param = `?registryCode=${this.registryCode}`;
    if(this.filterCode) param += `&filterCode=${this.filterCode}`;
    if(this.searchString) param += `&searchString=${this.searchString}`;

    if(this.filterSearchUrl) {
      param += this.filterSearchUrl;
      if(key) {
        let next = this.getNextFieldNumber(this.filterSearchUrl);
        param += `&field${next}=${this.fieldDict}&condition${next}=TEXT_EQUALS&key${next}=${key}`;
      }
    } else {
      if(key) param += `&field=${this.fieldDict}&condition=TEXT_EQUALS&key=${key}`;
    }

    param += `&fieldCode=${fieldCode}&countType=sum`;

    return new Promise(resolve => {
      rest.synergyGet(`api/registry/count_data${param}`, resolve, err => {
        console.log(`KanbanBoard ERROR [ getSumRowInRegistry ]: ${JSON.stringify(err)}`);
        resolve(null);
      });
    });
  },

  getDictInfo: async function(){
    const {code, title, value, color} = this.statusDict;
    const {columns, items, name} = await appAPI.getDictionary(code);
    this.columns = [];
    for(let key in items) {
      const item = items[key];
      const parseItem = {
        key: item[value]?.value,
        countInPart: this.countInPart,
        currentPage: 0
      };
      if(item.hasOwnProperty(title)) {
        if(item[title].hasOwnProperty('translations')) {
          parseItem.name = item[title]?.translations[AS.OPTIONS.locale];
        } else {
          parseItem.name = item[title]?.value;
        }
      }

      if(color) parseItem.color = item[color]?.value;
      this.columns.push(parseItem);
    }
    this.columns.sort((a,b) => a.key - b.key);
  },

  allowDrop: function(event) {
    event.preventDefault();
  },
  drag: function(param) {
    const {event, dataUUID, documentID} = param;
    const parentColumnID = event.target.dataset.parentcolumnid;
    event.originalEvent.dataTransfer.setData("dataUUID", dataUUID);
    event.originalEvent.dataTransfer.setData("documentID", documentID);
    event.originalEvent.dataTransfer.setData("parentColumnID", parentColumnID);
  },

  openDocument: function(dataUUID, updateData = false) {
    if(this.rights.includes('rr_read')) {
      if(updateData) {
        openFormPlayer(dataUUID, null, () => {
          this.reset();
          this.render();
        });
      } else {
        openFormPlayer(dataUUID);
      }
    } else {
      showMessage('У вас нет прав на просмотр', 'warning');
    }
  },

  cutString: function(str) {
    return str.length > this.stringLength ? `${str.substr(0, this.stringLength)}...` : str;
  },

  getTitleBlock: function(text, dataUUID){
    const block = $('<div>', {class: 'column-card-block title'});
    const blockValue = $('<div>', {class: 'column-card-block-value'});

    block.append(blockValue);
    blockValue.text(this.cutString(text));
    blockValue.attr('uk-tooltip', `title: ${text}; duration: 300;`);

    block.on('click', e => {
      this.openDocument(dataUUID, true);
    });

    return block;
  },

  getSumBlock: function(sum, prefix){
    const block = $('<div>', {class: 'column-card-block sum'});
    const blockValue = $('<div>', {class: 'column-card-block-value'});

    block.append(blockValue);
    blockValue.text(`${sum} ${prefix}`);

    return block;
  },

  getReglinkBlock: function(title, code, fieldValue, fieldKey){
    if(!fieldKey.hasOwnProperty(code)) return;

    const block = $('<div>', {class: 'column-card-block reglink'});
    const blockTitle = $('<div>', {class: 'column-card-block-title'});
    const blockValue = $('<div>', {class: 'column-card-block-value'});

    block.append(blockTitle, blockValue);
    blockTitle.text(`${title}:`);
    blockValue.text(fieldValue[code]);

    block.on('click', async e => {
      const dataUUID = await appAPI.getAsfDataUUID(fieldKey[code]);
      this.openDocument(dataUUID);
    });

    return block;
  },

  getUserBlock: function(title, value){
    const block = $('<div>', {class: 'column-card-block user'});
    const blockTitle = $('<div>', {class: 'column-card-block-title'});
    const blockValue = $('<div>', {class: 'column-card-block-value'});

    block.append(blockTitle, blockValue);
    blockTitle.text(`${title}:`);
    blockValue.text(value);

    return block;
  },

  getDefaultBlock: function(title, value){
    const block = $('<div>', {class: 'column-card-block'});
    const blockTitle = $('<div>', {class: 'column-card-block-title'});
    const blockValue = $('<div>', {class: 'column-card-block-value'});

    block.append(blockTitle, blockValue);
    blockTitle.text(`${title}:`);
    blockValue.text(value);

    return block;
  },

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

  contextMenu: function(el, dataRow){
    let isDelete = false;
    if(this.rights.indexOf('rr_delete') !== -1 && dataRow.status != 'STATE_NOT_FINISHED') isDelete = true;

    el.on('contextmenu', event => {
      $('.board-context-menu').remove();
      $('<div>', {class: 'board-context-menu'})
      .css({
        "left": event.pageX + 'px',
        "top": event.pageY + 'px'
      })
      .appendTo('body')
      .append(
        $('<ul class="uk-nav-default uk-nav-parent-icon" uk-nav>')
        .append($(`<li ><a href="javascript:void(0);"><span class="uk-margin-small-right" uk-icon="icon: push"></span>Открыть</a></li>`)
          .on('click', e => {
            this.openDocument(dataRow.dataUUID, true);
          })
        )
        .append('<li class="uk-nav-divider"></li>')
        .append($(`<li ${isDelete ? '' : 'class="uk-disabled"'} ><a href="javascript:void(0);"><span class="uk-margin-small-right" uk-icon="icon: trash"></span>Удалить запись</a></li>`)
          .on('click', e => {
            isDelete ? this.removeRegistryRow(dataRow.dataUUID, e) : false;
          })
        )
      )
      .show('fast');
      return false;
    });
  },

  getColumnCard: function(item, columnID){
    const {dataUUID, documentID, fieldValue, fieldKey} = item;
    const cardContainer = $('<div>', {class: 'column-card', id: `card-${dataUUID}`});

    cardContainer.attr('data-uuid', dataUUID);
    cardContainer.attr('data-documentid', documentID);
    cardContainer.attr('data-parentcolumnid', columnID);
    cardContainer.attr('draggable', true);

    for(let i = 0; i < this.fields.length; i++) {
      const {title, code, type, prefix = '₸'} = this.fields[i];
      if(!fieldValue.hasOwnProperty(code)) continue;

      switch (type) {
        case 'title': cardContainer.append(this.getTitleBlock(fieldValue[code], dataUUID)); break;
        case 'sum': cardContainer.append(this.getSumBlock(fieldValue[code], prefix)); break;
        case 'reglink': cardContainer.append(this.getReglinkBlock(title, code, fieldValue, fieldKey)); break;
        case 'user': cardContainer.append(this.getUserBlock(title, fieldValue[code])); break;
        default: cardContainer.append(this.getDefaultBlock(title, fieldValue[code])); break;
      }
    }

    cardContainer.on("dragstart", event => this.drag({event, dataUUID, documentID}));

    this.contextMenu(cardContainer, item);

    return cardContainer;
  },

  renderColumn: async function(column, data){
    const {name, key, color, recordsCount} = column;
    const columnContainer = $('<div>', {class: 'column-container', id: `column-${key}`});
    const columnTitle = $('<span>', {class: 'column-title'});
    const columnSum = $('<span>', {class: 'column-sum'});
    const columData = $('<div>', {class: 'column-data'});
    const getRowsButton = $('<span>', {class: 'column-get-rows-button'});
    let rowsButtonIsHidden = true;

    columnContainer.append(columnTitle, columnSum, columData);
    boardContent.append(columnContainer);

    if(this.sum) {
      const {cmp, prefix = '₸'} = this.sum;
      const sumResult = await this.getSumRowInRegistry(cmp, key);
      const sum = new Intl.NumberFormat('ru-RU').format(Number(sumResult[`${cmp}_0`]) || 0) + ` ${prefix}`;
      columnSum.text(sum);
    } else {
      columnSum.hide();
    }

    if(color) columnTitle.css('background', color);

    columnTitle.text(`${name} (${recordsCount})`);
    columnTitle.attr('uk-tooltip', `title: ${name} (${recordsCount}); duration: 300;`);
    getRowsButton.text('ещё...');

    data.forEach(item => {
      const card = this.getColumnCard(item, key);
      columData.append(card);
    });

    if(column.countInPart < recordsCount) {
      columData.append(getRowsButton);
      rowsButtonIsHidden = false;

      getRowsButton.on('click', async e => {
        Cons.showLoader();
        column.currentPage++;
        const searchResult = await this.searchInRegistry(this.getUrlParam(column));

        if(searchResult && searchResult.recordsCount > 0) {
          searchResult.result.forEach(item => {
            const card = this.getColumnCard(item, key);
            columData.append(card);
            if((column.countInPart * (column.currentPage + 1)) < recordsCount) {
              getRowsButton.detach().appendTo(columData);
              rowsButtonIsHidden = false;
            } else {
              getRowsButton.remove();
              rowsButtonIsHidden = true;
            }
          });
        } else {
          getRowsButton.hide();
          rowsButtonIsHidden = true;
        }
        Cons.hideLoader();
      });
    }

    columData.on('drop', async event => {
      event.preventDefault();
      const dataUUID = event.originalEvent.dataTransfer.getData("dataUUID");
      const parentColumnID = event.originalEvent.dataTransfer.getData("parentColumnID");
      const dataColumn = event.target.closest('.column-data');
      const parentColumn = this.columns.find(x => x.key == parentColumnID);

      if(parentColumn.key == column.key) return;

      Cons.showLoader();

      const mergeResult = await appAPI.mergeFormData({
        uuid: dataUUID,
        data: [{
          id: this.fieldDict,
          type: "listbox",
          value: column.name,
          key: column.key
        }]
      });

      if(mergeResult) {
        dataColumn.appendChild(document.getElementById(`card-${dataUUID}`));
        parentColumn.recordsCount--;
        column.recordsCount++;

        columnTitle.text(`${column.name} (${column.recordsCount})`);
        $(`#column-${parentColumnID} > .column-title`).text(`${parentColumn.name} (${parentColumn.recordsCount})`);
        $(`#card-${dataUUID}`).attr('data-parentcolumnid', column.key);

        if(this.sum) {
          const {cmp, prefix = '₸'} = this.sum;
          const parentSumResult = await this.getSumRowInRegistry(cmp, parentColumnID);
          const currentSumResult = await this.getSumRowInRegistry(cmp, key);

          const parentSum = new Intl.NumberFormat('ru-RU').format(Number(parentSumResult[`${cmp}_0`]) || 0) + ` ${prefix}`;
          const currentSum = new Intl.NumberFormat('ru-RU').format(Number(currentSumResult[`${cmp}_0`]) || 0) + ` ${prefix}`;
          columnSum.text(currentSum);
          $(`#column-${parentColumnID} > .column-sum`).text(parentSum);
        }

        if(!rowsButtonIsHidden) getRowsButton.detach().appendTo(columData);
      } else {
        showMessage("Произошла ошибка при смене статуса", 'error');
      }

      Cons.hideLoader();
    }).on('dragover', this.allowDrop);
  },

  render: async function(){
    boardContent.empty();
    for(let i = 0; i < this.columns.length; i++) {
      const column = this.columns[i];
      const url = this.getUrlParam(column);
      const searchResult = await this.searchInRegistry(url);
      column.recordsCount = searchResult.recordsCount;
      this.renderColumn(column, searchResult.result);
    }
  },

  reset: function(){
    this.columns.forEach(column => column.currentPage = 0);
  },

  init: async function(params){
    Cons.showLoader();
    try {
      const {
        registryCode,
        filterCode = null,
        statusDict,
        fields,
        fieldDict,
        countInPart = 5,
        sum,
        searchString = null
      } = params;

      if(!registryCode) throw new Error(`Не передан параметр registryCode`);
      if(!statusDict) throw new Error(`Не передан параметр statusDict`);
      if(!fieldDict) throw new Error(`Не передан параметр fieldDict`);

      const registryList = await getRegistryList();
      const registry = registryList.find(x => x.registryCode == registryCode);

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

        const info = await appAPI.getRegistryInfo(registryCode);
        this.registryCode = registryCode;
        this.filterCode = filterCode;
        this.registryID = info.registryID;
        this.registryName = registry.registryName;
        this.rights = registry.rights;
        this.formCode = info.formCode;
        this.formId = info.formId;
        this.formName = info.name;

        this.statusDict = statusDict;
        this.fields = fields;
        this.fieldDict = fieldDict;
        this.countInPart = countInPart;

        this.sum = sum;
        this.searchString = searchString;

        await this.getDictInfo();
        this.render();
        Cons.hideLoader();
      } else {
        throw new Error(`Не найдено реестра с кодом: ${registryCode}`);
      }

    } catch (err) {
      Cons.hideLoader();
      console.log('ERROR init kanban board', err);
      showMessage(err.message, 'error');
    }
  }

}

compContainer.off()
.on('renderNewBoard', e => {
  if(!e.hasOwnProperty('eventParam')) return;
  KanbanBoard.init(e.eventParam);
}).on('updateBoard', e => {
  KanbanBoard.reset();
  KanbanBoard.render();
}).on('searchInRegistry', e => {
  if(!e.hasOwnProperty('eventParam')) return;
  const {searchString = null} = e.eventParam;
  KanbanBoard.searchString = searchString;
  KanbanBoard.reset();
  KanbanBoard.render();
}).on('changeFilterCode', e => {
  if(!e.hasOwnProperty('eventParam')) return;
  const {filterCode = null} = e.eventParam;
  KanbanBoard.filterCode = filterCode;
  KanbanBoard.reset();
  KanbanBoard.render();
}).on('filterRegistryRows', e => {
  if(!e.hasOwnProperty('eventParam')) return;
  const {filterSearchUrl} = e.eventParam;
  KanbanBoard.filterSearchUrl = filterSearchUrl;
  KanbanBoard.reset();
  KanbanBoard.render();
});

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