import EditableInput from './EditableInput';

class LayoutGridModel {
  constructor(items) {
    this.items = items;
  }

  setItems(items) {
    this.items = items;
  }
}

class LayoutGridView {

  constructor(selector, model, controller) {
    this.selector = selector;
    this.model = model;
    this.controller = controller;
  }

  render() {
    this.renderApiLayout();
  }

  clear(){
    this.selector.children().remove();
  }

  renderApiLayout() {
    const requestContainer = $(this.selector);
    requestContainer.children().remove();;

    const headerHtml = `
        <table class="layout_table" style="border-collapse: collapse; border: 1px gray solid;">
            <colgroup>
              <col style="width: 50px;">
              <col style="width: 80px;">
              <col style="width: 80px;">
              <col style="width: 120px;">
              <col style="width: 150px;">
              <col style="width: 60px;">
              <col style="width: 110px;">
              <col style="width: 80px;">
              <col style="width: 100px;">
              <col style="width: 80px;">
              <col style="width: 120px;">
              <col style="width: 120px;">
            </colgroup>
            <thead>
                <tr>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 80px;">#</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 40px;">ID</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 40px;">Parent</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 120px;">항목명(영문)</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 150px;">항목설명</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 60px;">깊이</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 110px;">아이템 유형</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 80px;">반복 횟수 </th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 100px;">반복 참조 필드</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 80px;">데이터 길이</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 120px;">값</th>
                    <th scope="col" style="border: 1px gray solid; text-align: center;width: 120px;">비고 <button type="button" class="btn btn-sm btn-outline-secondary add-layout-item"><i class="fas fa-plus"></i></button></th>
                </tr>
            </thead>
            <tbody>
        `;

    const footerHtml = `
                    </tbody>
                </table>
            `;

    const fieldsHtml = this.model.items ? this.model.items.map((item, index) => {
      return this.renderApiLayoutItem(item, index);
    }).join('') : '';

    requestContainer.append(headerHtml + fieldsHtml + footerHtml);

    requestContainer.find('.editable').each((index, editableElement) => {
      const editableInput = new EditableInput({
        name: editableElement.dataset.name,
        value: editableElement.dataset.value,
        style: {width: '120px'}
      });

      editableInput.init(editableElement, async (value) => {
        this.controller.setValue(editableElement.dataset.name, value);
      });
    });

    let totalLength = 0;
    this.model.items.forEach(item => {
      totalLength += parseInt(item.loutItemLength);
    });

    this.setupListeners();
  }

  getFieldValue(element) {
    if ($(element).is('select') || $(element).is('input[type="text"]') || $(element).is('input[type="number"]')) {
      return $(element).val();
    }
    if ($(element).is('input[type="checkbox"]')) {
      return $(element).is(':checked');
    }
  }

  async handleUIUpdate(event) {
    if (event) {
      event.preventDefault();
      const element = event.currentTarget;
      const fieldName = $(element).attr('name');
      const newValue = this.getFieldValue(element);
      if (fieldName !== '') {
        this.controller.setValue(fieldName, newValue);
      }
    }
    let totalLength = 0;
    this.model.items.forEach(item => {
      totalLength += parseInt(item.loutItemLength);
    });
  }

  setupListeners() {
    const table = this.selector.find('.layout_table');
    table.on('change', 'select.field, input.field', this.handleUIUpdate.bind(this));

    table.on('click', '.add-layout-item', async (event) => {
      await this.controller.addItem();
      this.renderApiLayout();
    });

    table.on('click', '.move-up', async (event) => {
      const index = $(event.currentTarget).data('index');
      await this.controller.moveUp(index);
      this.renderApiLayout();
    });

    table.on('click', '.move-down', async (event) => {
      const index = $(event.currentTarget).data('index');
      await this.controller.moveDown(index);
      this.renderApiLayout();
    });

    table.on('click', '.delete', async (event) => {
      const index = $(event.currentTarget).data('index');
      await this.controller.deleteItem(index);
      this.renderApiLayout();
    });
  }

  renderApiLayoutItem(item, index) {
    if (item.value === null) {
      item.value = '';
    }

    return `
        <tr class="layout-grid-row">
            <td class="layout-grid-cell" style="width: 80px; text-align: center;">
              <span style="width: 80px; text-align: center;">${item.loutItemSerno}</span>
            </td>
            <td class="layout-grid-cell">
              <input type="text" class="form-control field" name="items[${index}].id" value="${item.id}">
            </td>
            <td class="layout-grid-cell">
              <input type="text" class="form-control field" name="items[${index}].parent" value="${item.parent}">
            </td>
            <td class="layout-grid-cell">
              <input type="text" class="form-control field" name="items[${index}].loutItemName" value="${item.loutItemName}">
            </td>
            <td class="layout-grid-cell">
              <input type="text" class="form-control field" name="items[${index}].loutItemDesc" value="${item.loutItemDesc}">
            </td>
            <td class="layout-grid-cell">
              <input type="number" class="form-control field" style="width: 60px;" name="items[${index}].loutItemDepth" min="1" value="${item.loutItemDepth}">
            </td>
            <td class="layout-grid-cell">
                <select name="items[${index}].loutItemType" class="form-select field">
                    <option value="Field" ${item.loutItemType === 'Field' ? 'selected' : ''}>Field</option>
                    <option value="Grid" ${item.loutItemType === 'Grid' ? 'selected' : ''}>Grid</option>
                    <option value="Group" ${item.loutItemType === 'Group' ? 'selected' : ''}>Group</option>
                    <option value="Attr" ${item.loutItemType === 'Attr' ? 'selected' : ''}>Attr</option>
                </select>
            </td>
            <td class="layout-grid-cell">
              <input type="text" class="form-control field" style="width: 80px;" name="items[${index}].loutItemOccCnt" min="0" value="${item.loutItemOccCnt}">
            </td>
            <td class="layout-grid-cell">
              <input type="text" class="form-control field" name="items[${index}].loutItemOccRef" value="${item.loutItemOccRef}"></td>
            <td class="layout-grid-cell">
              <input type="number" class="form-control field" style="width: 80px;" name="items[${index}].loutItemLength" min="1" value="${item.loutItemLength}">
            </td>
            <td class="layout-grid-cell">
              ${item.loutItemType === 'Field' ? `<div class="editable" data-name="items[${index}].value" data-value="${item.value}"></div>` : ''}
            </td>
            <td  class="layout-grid-cell" style="width: 120px; text-align: center;">
              <div style="width: 120px !important;">
                <button type="button" class="btn btn-sm btn-outline-secondary move-up" data-index="${index}"><i class="fas fa-arrow-up"></i></button>
                <button type="button" class="btn btn-sm btn-outline-secondary move-down" data-index="${index}"><i class="fas fa-arrow-down"></i></button>
                <button type="button" class="btn btn-sm btn-outline-secondary delete" data-index="${index}"><i class="fas fa-trash-alt"></i></button>
              </div>
            </td>
        </tr>
    `;
  }

}

class LayoutGridController {
  constructor(model, view, callback) {
    this.model = model;
    this.view = view;
    this.view.controller = this;
    this.callback = callback;
    this.init();
  }

  init() {
    this.view.render();
  }

  recalculateSerno() {
    // Reassign loutItemSerno sequentially based on the current order
    this.model.items.forEach((item, index) => {
      item.loutItemSerno = index + 1;  // Assuming you want to start numbering from 1
    });
  }

  async addItem() {
    let item = {
      'id': this.getLastId(),
      'parent': 0,
      'level': 1,
      'loutName': '',
      'loutItemName': '',
      'loutItemDesc': '',
      'loutItemDepth': 1,
      'loutItemType': 'Field',
      'loutItemOccCnt': '',
      'loutItemOccRef': '',
      'loutItemDataType': 'String',
      'loutItemLength': 1,
      'loutItemDecimal': 0,
      'loutItemDefault': '',
      'loutItemMaskYn': 'N',
      'loutItemMaskOffset': 0,
      'loutItemMaskLength': 0,
      'parentLoutItemIndex': 0,
      'expanded': true,
      'isLeaf': true,
      'LOUTITEMPATH': '',
      'value': '',
      'loutItemSerno': 0
    };
    this.model.items.push(item);
    this.recalculateSerno();
    await this.callback(this.model);
  }

  async moveUp(index) {
    if (index > 0) {
      const temp = this.model.items[index];
      this.model.items[index] = this.model.items[index - 1];
      this.model.items[index - 1] = temp;
      this.recalculateSerno();
      await this.callback(this.model);
    }
  }

  async moveDown(index) {
    if (index < this.model.items.length - 1) {
      const temp = this.model.items[index];
      this.model.items[index] = this.model.items[index + 1];
      this.model.items[index + 1] = temp;
      this.recalculateSerno();
      await this.callback(this.model);
    }
  }

  async setValue(name, value){
    _.set(this.model, name, value);
    await this.callback(this.model);
  }

  async deleteItem(index) {
    this.model.items.splice(index, 1);
    this.recalculateSerno();
    await this.callback(this.model);
  }

  getLastId() {
    let lastId = 0;
    this.model.items.forEach(item => {
      if (item.id > lastId) {
        lastId = item.id;
      }
    });
    return lastId + 1;
  }

  rebuild(newItems) {
    this.model.setItems(newItems);
    this.view.clear();
    this.init();
  }
}

class LayoutGrid {
  constructor(selector, layout, callback) {
    this.model = new LayoutGridModel(layout.layoutItems);
    this.view = new LayoutGridView(selector, this.model, this);
    this.controller = new LayoutGridController(this.model, this.view, callback);
  }

  rebuild(layout) {
    this.controller.rebuild(layout.layoutItems);
    this.controller.callback(this.model);
  }
}

export default LayoutGrid;
