<!--
  Program: Common code
  Author: SDL
  Brief: Common code detail
-->
<template>
  <!-- SUB Contents -->
  <div class="ui--content-wrapper">
    <sdl-breadcrumb></sdl-breadcrumb>
    <!-- group code information -->
    <div class="ui--form-heading">
      <h4 class="d-inline-block">{{ $t('sdl.commonCode.label.groupCodeInfo') }}</h4>
      <div class="float-end" v-show="viewMode !== 'NEW'">
        <button type="button" class="btn btn-secondary btn-sm" @click="gotoList">
          {{ $t('sdl.common.label.list') }}
        </button>
        <button type="button" class="btn btn-secondary btn-sm" @click="deleteGroupCode">
          {{ $t('sdl.common.label.delete') }}
        </button>
        <button type="button" class="btn btn-primary btn-sm" @click="saveGroupCode">
          {{ $t('sdl.common.label.save') }}
        </button>
      </div>
    </div>

    <!-- Group code registration -->
    <form @submit.prevent name="groupCodeForm">
      <table class="table table-bordered ui--table-form ui--table-form-view mb-5" v-if="groupCode !== null">
        <colgroup>
          <col style="width:12.5%" />
          <col style="width:35.5%" />
          <col style="width:12.5%" />
          <col style="width:35.5%" />
        </colgroup>
        <tbody>
          <tr>
            <th class="text-nowrap" scope="row">
              {{ $t('sdl.commonCode.label.groupCode') }}<span class="ui--text-required">*</span>
            </th>
            <td>
              <input
                type="text"
                class="form-control"
                :disabled="viewMode !== 'NEW'"
                v-model.trim="groupCode.commCodeTypeCode"
                v-validation="{
                  groupId: 'main',
                  valids: [
                    {
                      validFuncs: () => {
                        return groupCode.commCodeTypeCode.length <= 20;
                      },
                      errorMessage: 'sdl.commonCode.label.code20Characters',
                    },
                    {
                      validFuncs: () => {
                        const regId = /^[A-Za-z0-9`~!@#$%^&*()-_=+]*$/g;
                        if (!regId.test(groupCode.commCodeTypeCode)) {
                          return false;
                        }
                        return true;
                      },
                      errorMessage: 'sdl.commonCode.message.valid.notKorean',
                    },
                  ],
                }"
                errorMessage="sdl.samsung.validate.required"
              />
              <!-- Only English letters, numbers and special characters can be entered. -->
            </td>
            <th class="text-nowrap" scope="row">
              {{ $t('sdl.commonCode.label.codeNameDefault') }}<span class="ui--text-required">*</span>
            </th>
            <td>
              <input type="text" class="form-control" v-model="groupCode.label" v-validation="{ groupId: 'main' }" errorMessage="sdl.samsung.validate.required" />
            </td>
          </tr>
          <tr v-for="locale in $i18n.availableLocales" :key="locale">
            <th class="text-nowrap" scope="row">
              {{ $t('sdl.commonCode.label.label') }}({{ locale }})
            </th>
            <td>
              <input type="text" class="form-control" v-model="groupCode.labelJson[locale]"/>
            </td>
          </tr>
          <tr>
            <th class="text-nowrap" scope="row">{{ $t('sdl.common.label.description') }}</th>
            <td colspan="3">
              <textarea class="form-control" aria-label="textarea" rows="2" v-model="groupCode.description"></textarea>
            </td>
          </tr>
          <tr v-show="viewMode !== 'NEW'">
            <th class="text-nowrap" scope="row">{{ $t('sdl.common.label.createdBy') }}</th>
            <td><input type="text" readonly class="form-control-plaintext" :value="groupCode.firstRegrName" /></td>
            <th class="text-nowrap" scope="row">{{ $t('sdl.common.label.createdDate') }}</th>
            <td>
              <input
                type="text"
                readonly
                class="form-control-plaintext"
                :value="$filters.dateFormat(groupCode.firstRegDatetime)"
              />
            </td>
          </tr>
          <tr v-show="viewMode !== 'NEW'">
            <th class="text-nowrap" scope="row">{{ $t('sdl.common.label.updatedBy') }}</th>
            <td><input type="text" readonly class="form-control-plaintext" :value="groupCode.lastModrName" /></td>
            <th class="text-nowrap" scope="row">{{ $t('sdl.common.label.updatedDate') }}</th>
            <td>
              <input
                type="text"
                readonly
                class="form-control-plaintext"
                :value="$filters.dateFormat(groupCode.lastModDatetime)"
              />
            </td>
          </tr>
        </tbody>
      </table>
    </form>
    <hr class="mb-4" v-if="viewMode === 'NEW'" />
    <div class="ui--button-container" v-if="viewMode === 'NEW'">
      <button class="btn btn-secondary btn-lg" type="submit" @click="gotoList()">
        {{ $t('sdl.common.label.list') }}
      </button>
      <button class="btn btn-primary btn-lg" type="submit" @click="saveNewGroupCode()">
        {{ $t('sdl.common.label.save') }}
      </button>
    </div>
    <!--// group code information -->
    <hr class="mb-4" v-show="viewMode !== 'NEW'" />
    <!-- common code list -->
    <div class="ui--form-heading clearfix" v-show="viewMode !== 'NEW'">
      <h4 class="d-inline-block">{{ $t('sdl.commonCode.label.commonCodeList') }}</h4>
      <div class="float-end">
        <button type="button" class="btn btn-secondary btn-sm" @click="addCode()">
          {{ $t('sdl.common.label.add') }}
        </button>
        <!--<button type="button" class="btn btn-primary btn-sm">{{$t('sdl.common.label.save')}}</button>-->
      </div>
    </div>

    <div class="row mb-3" v-show="viewMode !== 'NEW'">
      <div class="col-3">
        <div class="ui--box-tree">
          <sdl-tree
            ref="tree"
            :data="treeData"
            :multiple="false"
            text-field-name="localeLabel"
            whole-row
            :draggable="false"
            @item-click="treeItemClick"
          />
        </div>
      </div>
      <div class="col-9">
        <table class="table table-bordered ui--table">
          <colgroup>
            <col style="width:5%" />
            <col style="width:15%" />
            <col style="width:15%" />
            <col style="" />
            <col style="width:10%" v-for="(index) in $i18n.availableLocales" :key="'col'+index" />
            <col style="width:5%" />
            <col style="width:5%" />
          </colgroup>
          <thead>
            <tr>
              <th scope="col"></th>
              <th scope="col">{{ $t('sdl.commonCode.label.code') }}</th>
              <th scope="col">{{ $t('sdl.commonCode.label.codeNameDefault') }}</th>
              <th scope="col">{{ $t('sdl.common.label.description') }}</th>
              <th scope="col" v-for="(locale, index) in $i18n.availableLocales" :key="'th'+index">{{ $t('sdl.commonCode.label.label') }}({{ locale }})</th>
              <th scope="col">{{ $t('sdl.common.label.edit') }}</th>
              <th scope="col">{{ $t('sdl.common.label.delete') }}</th>
            </tr>
          </thead>
          <!--      <tbody>-->
          <draggable v-bind="dragOptions" v-model="codeList" tag="tbody" @change="moveCodeList" handle=".drag-handle" item-key="codeId">
            <template #item="{ element }">
              <tr class="cursor-pointer-disabled">
                <td class="text-center drag-handle">
                  <i class="bi bi-grip-vertical" title="Move Row"></i>
                </td>
                <td>{{ element.code }}</td>
                <td>{{ element.label }}</td>
                <td>{{ element.description }}</td>
                <td v-for="(locale, index) in $i18n.availableLocales" :key="'td'+index">{{ element.labelJson[locale] }}</td>
                <td class="text-center">
                  <button class="btn btn-outline-secondary ui--btn-xs" @click="updateCode(element.codeId)">
                    {{ $t('sdl.common.label.edit') }}
                  </button>
                </td>
                <td class="text-center">
                  <button class="btn btn-outline-secondary ui--btn-xs" @click="deleteCode(element.codeId)">
                    {{ $t('sdl.common.label.delete') }}
                  </button>
                </td>
              </tr>
            </template>
          </draggable>

          <!--      </tbody>-->
        </table>
      </div>
    </div>
    <!--// common code list -->
  </div>
</template>

<script>
import axios from 'axios';
import draggable from 'vuedraggable';
import _ from 'lodash';
import { SDLUtil } from '@/utils';
import CommcodePopup from './popup/CommcodePopup.vue';
import SDLLocale from '@/mixin/SDLLocale';
import StoreParams from '@/mixin/StoreParams';

export default {
  mixins: [SDLLocale, StoreParams],
  data() {
    return {
      groupCodeId: '',
      viewMode: 'DETAIL',
      groupCode: {
        labelJson: {},
      },
      codeList: [],
      treeData: [],
      selectedTreeItemId: '',
      treeRawData: [],
      dragOptions: {
        animation: 200,
        group: 'codeList',
        disabled: false,
        ghostClass: 'ghost',
      },
    };
  },
  created() {
    this.groupCodeId = this.$route.params.groupcode;
    this.init();
  },
  methods: {
    init() {
      if (this.groupCodeId) {
        this.viewMode = 'DETAIL';
        this.groupCode = {
          labelJson: {},
        };
        this.getGroupCode().then(() => this.getCodes());
      } else {
        this.viewMode = 'NEW';
        this.groupCode = {
          commCodeTypeCode: '',
          label: '',
          labelJson: {},
          description: '',
        };
      }
    },
    // on a list
    gotoList() {
      this.goBackToList();
    },
    // Retrieving Group Code Information
    getGroupCode() {
      return new Promise((resolve, reject) => {
        const url = `${SDLUtil.API_URL}/commcode/groupcodes/${this.groupCodeId}`;
        // Loading bar
        SDLUtil.showLoadingBar(true);
        axios
          .get(url)
          .then(({ data }) => {
            this.groupCode = data;
            SDLUtil.showLoadingBar(false);
            resolve();
          })
          .catch(err => {
            console.error(err);
            SDLUtil.showLoadingBar(false);
            reject();
          });
      });
    },
    getCodes() {
      return new Promise((resolve, reject) => {
        const url = `${SDLUtil.API_URL}/commcode/groupcodes/${this.groupCodeId}/commcodes`;
        SDLUtil.showLoadingBar(true);
        axios
          .get(url)
          .then(({ data }) => {
            this.treeRawData = data;
            this.makeTreeData(data);
            SDLUtil.showLoadingBar(false);
            resolve();
          })
          .catch(err => {
            console.error(err);
            SDLUtil.showLoadingBar(false);
            reject();
          });
      });
    },
    makeTreeData(data) {
      const codes = data.map(code => ({
        ...code,
        id: code.codeId,
        localeLabel: this.getLabel(code),
        value: code,
      }));

      const root = {
        ...this.groupCode,
        id: this.groupCodeId,
        localeLabel: this.getLabel(this.groupCode),
        opened: true,
        selected: true,
        value: this.groupCode,
      };

      const getChildren = parentId => {
        let children = codes.filter(code => code.upperCodeId === parentId);
        children = _.sortBy(children, ['ord']);
        children.forEach(code => {
          code.dragDisabled = false;
          // If there is a child node
          if (_.find(codes, ['upperCodeId', code.codeId])) {
            code.opened = false;
            code.children = getChildren(code.codeId);
          } else {
            // If no child node exists, icon can be changed
            // m.icon = 'tree-node';
            // delete m.opened;
          }
        });
        return children;
      };

      // 1 depth code added
      root.children = _.sortBy(codes.filter(code => code.hierarchyLevel === 1), ['ord']);
      // From 2 depth looping
      root.children.forEach(code => {
        // console.info(code.codeId);
        if (_.find(codes, ['upperCodeId', code.codeId])) {
          code.opened = false;
          code.children = getChildren(code.codeId);
        } else {
          // If no child node exists, icon can be changed
          // code.icon = 'tree-node';
          // delete code.opened;
        }
      });

      this.treeData = [root];
      this.$refs.tree.initializeData(this.treeData);
      // 루트 선택
      this.selectedTreeItemId = this.groupCodeId;
      this.makeCodeList();
    },
    makeCodeList() {
      const selectedTreeId = this.selectedTreeItemId;
      // console.info('makeCodeList', selectedTreeId);
      if (selectedTreeId === this.groupCodeId) {
        // root 1 depth
        this.codeList = _.sortBy(this.treeRawData.filter(code => code.hierarchyLevel === 1), ['ord']);
      } else {
        // 기타
        this.codeList = _.sortBy(this.treeRawData.filter(code => code.upperCodeId === selectedTreeId), ['ord']);
      }
    },
    saveGroupCode() {
      if (SDLUtil.onSubmitValidation('main')) return;
      SDLUtil.confirm({
        msg: 'sdl.common.message.doSave',
        title: 'sdl.common.label.save',
        okLabel: 'sdl.common.label.confirm',
        cancelLabel: 'sdl.common.label.cancel',
        onOkEvt: () => {
          SDLUtil.showLoadingBar(true);
          axios
            .put(`${SDLUtil.API_URL}/commcode/groupcodes/${this.groupCodeId}`, this.groupCode)
            .then(() => {
              SDLUtil.showLoadingBar(false);
              this.getGroupCode().then(() => {
                this.getCodes();
              });
              SDLUtil.loadAllCommCodeList();
            })
            .catch(err => {
              console.error(err);
              SDLUtil.showLoadingBar(false);
              SDLUtil.errorAlert(err);
            });
        },
        onCancelEvt: () => console.log('cancel'),
      });
    },
    deleteGroupCode() {
      SDLUtil.confirm({
        msg: 'sdl.common.message.doDelete',
        title: 'sdl.common.label.delete',
        okLabel: 'sdl.common.label.delete',
        cancelLabel: 'sdl.common.label.cancel',
        onOkEvt: () => {
          SDLUtil.showLoadingBar(true);
          axios
            .delete(`${SDLUtil.API_URL}/commcode/groupcodes/${this.groupCodeId}`)
            .then(() => {
              SDLUtil.showLoadingBar(false);
              SDLUtil.loadAllCommCodeList();
              // 목록으로
              this.gotoList();
            })
            .catch(err => {
              SDLUtil.showLoadingBar(false);
              console.error(err);
              SDLUtil.errorAlert(err);
            });
        },
        onCancelEvt: () => console.log('cancel'),
      });
    },
    saveNewGroupCode() {
      if (SDLUtil.onSubmitValidation('main')) return;
      // validation
      if (this.groupCode.commCodeTypeCode === '' || this.groupCode.label === '') {
        SDLUtil.alert('sdl.commonCode.message.valid.mandatory');
        return;
      }

      SDLUtil.confirm({
        msg: 'sdl.common.message.doSave',
        title: 'sdl.common.label.save',
        okLabel: 'sdl.common.label.confirm',
        cancelLabel: 'sdl.common.label.cancel',
        onOkEvt: () => {
          SDLUtil.showLoadingBar(true);
          axios
            .get(`${SDLUtil.API_URL}/commcode/groupcodes/${this.groupCode.commCodeTypeCode}/check-duplicate`)
            .then(result => {
              if (!result.data) {
                axios
                  .post(`${SDLUtil.API_URL}/commcode/groupcodes`, this.groupCode)
                  .then(({ data }) => {
                    console.info('success', data);
                    SDLUtil.showLoadingBar(false);
                    this.groupCodeId = this.groupCode.commCodeTypeCode;
                    // 상세보기로 이동
                    this.$router.replace({
                      path: `${SDLUtil.WEB_CONTEXT_PATH}/admin/etc/groupcodes/detail/${this.groupCode.commCodeTypeCode}`,
                    });
                    SDLUtil.loadAllCommCodeList();
                  })
                  .catch(err => {
                    SDLUtil.showLoadingBar(false);
                    SDLUtil.errorAlert(err);
                  });
              } else {
                SDLUtil.showLoadingBar(false);
                SDLUtil.alert('sdl.commonCode.message.registeredOrRecorded');
              }
            })
            .catch(err => {
              SDLUtil.showLoadingBar(false);
              SDLUtil.errorAlert(err);
            });
        },
        onCancelEvt: () => console.log('cancel'),
      });
    },
    addCode() {
      const maxOrd = Math.max(...this.codeList.map(code => code.ord), 0);
      let hierarchyLevel = 1;
      const selectedTreeItem = _.find(this.treeRawData, ['codeId', this.selectedTreeItemId]);
      if (selectedTreeItem) {
        hierarchyLevel = selectedTreeItem.hierarchyLevel + 1;
      }
      SDLUtil.show(
        CommcodePopup,
        {
          hierarchyLevel,
          groupCodeId: this.groupCodeId,
          upperCodeId: this.selectedTreeItemId === this.groupCodeId ? undefined : this.selectedTreeItemId,
          title: SDLUtil.getMsgProp('sdl.commonCode.label.codeReg'),
          ord: maxOrd + 1,
          refreshCodes: () => {
            const openId = this.selectedTreeItemId;
            this.getCodes().then(() => {
              this.$refs.tree.initializeData(this.treeData);
              this.openTreeItemById(openId, true);
            });
            SDLUtil.loadAllCommCodeList();
          },
        },
        {
          width: 500,
          height: 'auto',
        },
      );
    },
    updateCode(codeId) {
      SDLUtil.show(
        CommcodePopup,
        {
          codeId,
          groupCodeId: this.groupCodeId,
          upperCodeId: this.selectedTreeItemId === this.groupCodeId ? undefined : this.selectedTreeItemId,
          title: SDLUtil.getMsgProp('sdl.commonCode.label.codeMod'),
          refreshCodes: () => {
            const openId = this.selectedTreeItemId;
            this.getCodes().then(() => {
              this.openTreeItemById(openId, true);
            });
            SDLUtil.loadAllCommCodeList();
          },
        },
        {
          width: 500,
          height: 'auto',
        },
      );
    },
    deleteCode(codeId) {
      SDLUtil.confirm({
        msg: 'sdl.common.message.doDelete',
        title: 'sdl.common.label.delete',
        okLabel: 'sdl.common.label.delete',
        cancelLabel: 'sdl.common.label.cancel',
        onOkEvt: () => {
          SDLUtil.showLoadingBar(true);
          axios
            .delete(`${SDLUtil.API_URL}/commcode/groupcodes/${this.groupCodeId}/commcodes/${codeId}`)
            .then(() => {
              SDLUtil.showLoadingBar(false);
              const openId = this.selectedTreeItemId;
              this.getCodes().then(() => {
                this.openTreeItemById(openId, true);
              });
              SDLUtil.loadAllCommCodeList();
            })
            .catch(err => {
              SDLUtil.showLoadingBar(false);
              console.error(err);
              SDLUtil.errorAlert(err);
            });
        },
        onCancelEvt: () => console.log('cancel'),
      });
    },
    moveCodeList(event) {
      if (event.moved) {
        // console.info(this.codeList);
        this.codeList = this.codeList.map((code, idx) => {
          if (code.ord !== idx + 1) {
            code.isEdited = true;
            code.ord = idx + 1;
          }
          return code;
        });

        const changeList = this.codeList
          .filter(code => code.isEdited)
          .map(code => ({
            codeId: code.codeId,
            ord: code.ord,
          }));
        const openId = this.selectedTreeItemId;
        const fetchURL = ({ codeId, ord }) => axios.put(`${SDLUtil.API_URL}/commcode/groupcodes/${this.groupCodeId}/commcodes/${codeId}/ord/${ord}`);
        SDLUtil.showLoadingBar(true);
        Promise.all(changeList.map(fetchURL))
          .then(() => {
            this.getCodes().then(() => {
              this.openTreeItemById(openId, true);
            });
            SDLUtil.showLoadingBar(false);
            SDLUtil.loadAllCommCodeList();
          })
          .catch(err => {
            console.error(err);
            SDLUtil.showLoadingBar(false);
            SDLUtil.errorAlert(err);
          });
        // console.info('changeList', changeList);
      }
    },
    treeItemClick(item) {
      // console.info('treeItemClick', item.data.id);
      this.selectedTreeItemId = item.data.id;
      this.makeCodeList();
    },
    openTreeItemById(treeId, isSelected = true) {
      setTimeout(() => {
        this.$refs.tree.handleRecursionNodeChilds(this.$refs.tree, node => {
          if (node.model && node.model.id === treeId) {
            node.model.opened = true;
            const parentId = node.model.upperCodeId;
            if (parentId) {
              this.openTreeItemById(parentId, false);
            }
            node.model.selected = isSelected;
            if (isSelected) {
              // root 체크
              if (treeId !== this.groupCodeId) {
                this.treeData[0].selected = false;
              }
              this.treeItemClick(node);
            }
          }
        });
      });
    },
  },
  watch: {
    locale() {
      const changeTreeLocale = treeItem => {
        treeItem.localeLabel = this.getLabel(treeItem);
        treeItem.children.forEach(child => changeTreeLocale(child));
      };
      if (this.viewMode !== 'NEW') changeTreeLocale(this.treeData[0]);
    },
  },
  components: {
    draggable,
  },
};
</script>

<style scoped>
/*.ghost {*/
/*  opacity: 0.5;*/
/*  background: #c8ebfb;*/
/*}*/
.drag-handle {
  cursor: move;
}
.tree-selected {
  background-color: #e9ecef !important;
}
</style>
