import { LayoutTable, CATEGORIES } from "../../configuration/constants";
import combineSvg from '../../assets/combine.svg';
import separateSvg from '../../assets/separate.svg';

export default {
  // 组件名称
  name: LayoutTable,

  // 前面板html模板
  viewTemplate() {
    return `
      <div data-gjs-type="${LayoutTable}" class="${LayoutTable}">
        <table><tbody>
        <tr><td></td><td></td><td></td></tr>
        <tr><td></td><td></td><td></td></tr>
        </tbody></table>
      </div>
    `;
  },
  // 前面板html样式
  viewStyle() {
    return `
      <style>
        .${LayoutTable} {
          width: 300px;
          height: 120px;
        }
        .${LayoutTable} table {
          width: 100%;
          height: 100%;
          border-collapse: collapse;
        }
        .${LayoutTable} th, .${LayoutTable} td {
          border: 1px solid #ddd;
        }
      </style>
    `;
  },

  // 编辑器右侧块管理器中显示属性配置
  blockOptions() {
    return null;
  },

  // 组件属性
  componentOptions() {
    return {
      childrenSelectable: false,
      resizable: true,
      highlightable: false,
    };
  },

  onModelScript() {},

  onViewInit({ editor }) {
    const comps = this.model.get("components");
    comps.length && this.setTdResizable(comps);

    this.rowIndex = null;
    this.colIndex = null;
    this.$multiSelector = null;
    this.selectorRectangle = { left: 0, top: 0, width: 0, height: 0 };
    this.$separate = $(
      `<div class="combination-icons separate">${separateSvg}</div>`
    );
    this.$combine = $(
      `<div class="combination-icons combine">${combineSvg}</div>`
    );
    editor.on("component:selected", (comp) => {
      if (comp.get("type") !== "cell") {
        this.$multiSelector && this.deactivate();
      }
    });
  },

  viewMethods: () => {
    return {
      events: {
        'dblclick': 'elDblclick',
        'click td': 'tdClick'
      },
      computeSelectorRectangle(direction) {
        const $tbody = this.$el.find('tbody');
        let left = 0;
        let top = 0;
        let width = 0;
        let height = 0;
        if (typeof this.rowIndex == 'number' && direction !== 'rowspan') {
          const minCol = typeof this.colIndex == 'number' ? this.colIndex : _.min(this.colIndex);
          const maxCol = typeof this.colIndex == 'number' ? this.colIndex : _.max(this.colIndex);
          const $tr = $tbody.children('tr').eq(this.rowIndex);
          const offset = $tr.children('td').eq(minCol).offset();
          let offsetWidth = 0;
          for (let k = minCol; k <= maxCol; k++) {
            offsetWidth += $tr.children("td").eq(k).outerWidth();
          }
          left = offset.left;
          top = offset.top;
          width = offsetWidth;
          height = $tr.height();
        } else if (typeof this.colIndex == 'number' && direction !== 'colspan') {
          // 相同列
          const minRow = typeof this.rowIndex == 'number' ? this.rowIndex : _.min(this.rowIndex);
          const maxRow = typeof this.rowIndex == 'number' ? this.rowIndex : _.max(this.rowIndex);
          const $firstTd = $tbody.children('tr').eq(minRow).children('td').eq(this.colIndex);
          const offset = $firstTd.offset();
          let offsetHeight = 0;
          for (let j = minRow; j <= maxRow; j++) {
            const $tr = $tbody.children('tr').eq(j);
            offsetHeight += $tr.children('td').eq(this.colIndex).outerHeight();
          }
          left = offset.left;
          top = offset.top;
          width = $firstTd.width();
          height = offsetHeight
        } else {
          return;
        }
        this.selectorRectangle = { left, top, width, height };
      },
      addSelector(param) {
        const { left, top, width, height } = this.selectorRectangle;
        if (param) {
          this.$separate.css({ display: 'none' });
          this.$combine.css({ display: 'block' });
        } else {
          this.$separate.css({ display: 'block' });
          this.$combine.css({ display: 'none' });
        };
        if (!this.$multiSelector) {
          this.$multiSelector = $(`<div class="${GRAPESJS_PPFX}multiple-selector"></div>`);
          this.$toolbar = $(`<div class="${GRAPESJS_PPFX}multiple-selector-toolbar"></div>`);
          this.$toolbar.append(this.$combine)
          this.$toolbar.append(this.$separate);
          this.$multiSelector.append(this.$toolbar);
          const _this = this;

          this.$multiSelector.on('click', '.combine', function (e) {
            const tbody = _this.model.components().models[0].components().models[0];
            const tr_list = tbody.components().models;
            if (typeof _this.rowIndex == 'number') {
              const minCol = _.min(_this.colIndex);
              const maxCol = _.max(_this.colIndex);
              let colspan = _this.colIndex.length;
              const td_list = tr_list[_this.rowIndex].components().models;
              _.forEach(td_list.slice(minCol, maxCol + 1), (td, i) => {
                const _attr = td.getAttributes('colspan');
                if (_attr.colspan) {
                  colspan += (parseInt(_attr.colspan) - 1);
                }
                if (i > 0) {
                  td.remove();
                }
              });
              td_list[minCol].setAttributes({ colspan: colspan });
            } else if (typeof _this.colIndex == 'number') {
              const minRow = _.min(_this.rowIndex);
              const maxRow = _.max(_this.rowIndex);
              let rowspan = _this.rowIndex.length;
              _.forEach(tr_list.slice(minRow, maxRow + 1), (tr, i) => {
                const td = tr.components().models[_this.colIndex];
                const _rowspan = td.getAttributes('rowspan').rowspan;
                if (_rowspan) {
                  rowspan += (parseInt(_rowspan) - 1);
                }
                if (i > 0) {
                  td.remove();
                }
              });
              const first = tr_list[minRow].components().models[_this.colIndex];
              first.setAttributes({ rowspan: rowspan });
            }
            _this.deactivate();
          });
          this.$multiSelector.on('click', '.separate', function (e) {
            const tbody = _this.model.components().models[0].components().models[0];
            const tr_list = tbody.components().models;
            const tr = tbody.components().models[_this.rowIndex];
            const td = tr.components().models[_this.colIndex];
            let colspan = td.getAttributes("colspan").colspan;
            let rowspan = td.getAttributes("rowspan").rowspan;
            let removed = [];
            if (colspan) {
              td.setAttributes({ 'colspan': null });
              for (let i = 1; i < colspan; i++) {
                removed.push({ type: 'cell', classes: ['cell'] });
              }
              tr.append(removed, { at: _this.colIndex + 1 });
            } else if (rowspan) {
              td.setAttributes({ 'rowspan': null });
              for (let j = 1; j < rowspan; j++) {
                tr_list[_this.rowIndex + j].append({ type: 'cell', classes: ['cell'] }, { at: _this.colIndex });
              }
            }
            _this.deactivate();
          });
          $('#gjs-cv-tools').append(this.$multiSelector);
        }
        this.$multiSelector.css({ left, top, width, height }).show();
      },
      tdClick(ev) {
        const $current = $(ev.target);
        const current_row = $current.parent().index();
        const current_col = $current.index();
        const selected = editor.getSelected();
        if (ev.ctrlKey) {
          // 按ctrl键多选，combine
          const selectedAll = editor.getSelectedAll();
          let hasCombined = false;
          _.forEach(selectedAll, sel => {
            if (sel.get('type') == 'cell') {
              if (!hasCombined) {
                hasCombined = sel.getAttributes('colspan').colspan || sel.getAttributes('rowspan').rowspan;
              }
            }
          });
          if (hasCombined) return;
          if (selected && selected.get('type') == 'cell') {
            const $sel = selected.view.$el;
            const row = $sel.parent().index();
            const col = $sel.index();
            if (row == current_row && col == current_col) return;

            if (row == current_row && Math.abs(col - current_col) == 1) {
              this.rowIndex = row;
              if (!this.colIndex) this.colIndex = [col];
              if (_.indexOf(this.colIndex, current_col) == -1) this.colIndex.push(current_col);

            } else if (col == current_col && Math.abs(row - current_row) == 1) {
              if (!this.rowIndex) this.rowIndex = [row];
              if (_.indexOf(this.rowIndex, current_row) == -1) this.rowIndex.push(current_row);
              this.colIndex = col;
            }

            this.computeSelectorRectangle();
            this.addSelector(true);
          }
        } else if ($current.attr('colspan') || $current.attr('rowspan')) {
          // 若$current中含colspan 或rowspan，则可以separate
          this.rowIndex = current_row;
          this.colIndex = current_col;
          let direction = null;
          if ($current.attr('colspan')) {
            direction = "colspan";
          } else if ($current.attr('rowspan')) {
            direction = "rowspan";
          }
          this.computeSelectorRectangle(direction);
          this.addSelector(false);
        } else {
          this.deactivate();
        }
      },
      setTdResizable(comps) {
        comps.forEach(comp => {
          if (comp.get('type') === 'row') {
            comp.set('selectable', true);
          } else if (comp.get('type') === 'cell') {
            comp.set('resizable', true);
            comp.set('draggable', false);
          }

          const children = comp.components();
          children.length && this.setTdResizable(children);
        })
      },
      deactivate() {
        this.selectorRectangle = { left: 0, top: 0, width: 0, height: 0 };
        this.rowIndex = null;
        this.colIndex = null;
        if (this.$multiSelector) {
          this.$multiSelector.hide();
        }
      },
      elDblclick(ev) {
        ev.stopPropagation();
        if (this.model.get('childrenSelectable') == false) {
          if (this.$el.hasClass('no-events')) {
            this.model.components().forEach(m => {
              m.set('selectable', false);
              m.set('editable', true);
              m.set('removable', false);
              m.set('copyable', false);
            });
            this.$el.removeClass("no-events")
          } else {
            this.model.components().forEach(m => {
              m.set('selectable', false);
              m.set('editable', false);
            });
            this.$el.addClass("no-events")
          }
        }
      }
    }
  }
};
