<template>
  <div class="container" :style="isLoading ? { cursor: 'wait' } : {}">
    <!-- 로딩 시 화면을 덮는 반투명 오버레이 -->
    <div v-if="isLoading" class="loading-overlay">
      <div class="loading-div">
        <span>LOADING </span>
        <span class="anima">.</span>
        <span class="anima">.</span>
        <span class="anima">.</span>
      </div>
    </div>
    <div class="page-titleZone flex justify-between align-center align-start">
      <p class="main-title flex80"> 데이터 활용관리 {{ !pageId ? "등록" : "수정" }} </p>
    </div>
    <div class="content-wrap content flex100">
      <div class="custom-tab content-box">
        <div class="flex justify-start align-center no-gutter content-box">
          <div class="column-nav flex5">
            <ul>
              <li class="cursor" v-for="(item, idx) in navList" :key="idx" @click="fnChangeTab('nav', item.id)">
                <a :class="{ activeTab: activeTab === item.id }">
                  <svg-icon type="mdi" class="mb5" :path="item.iconPath" />
                  <p>{{ item.name }}</p>
                </a>
              </li>
            </ul>
          </div>
          <div class="content-box flex justify-between align-start flex95 no-gutter">
            <div :class="{
              'tab-zone flex align-start': true,
              flex30: !isTabZoneOpen,
            }">
              <div class="content-box" v-show="!isTabZoneOpen">
                <!-- 페이지정보탭 -->
                <div class="content-box tab-box pd10 overflow-y" v-show="activeTab === 'pageInfo'">
                  <div class="content-titleZone">
                    <div class="flex justify-between align-center">
                      <p class="box-title">페이지 정보</p>
                    </div>
                  </div>
                  <table class="form-table">
                    <tr>
                      <th>제목</th>
                      <td>
                        <input type="text" class="full-input" v-model="customTitle" />
                      </td>
                    </tr>
                    <tr>
                      <th>공개여부</th>
                      <td>
                        <div class="input-container flex">
                          <label class="radio-label">
                            <input type="radio" name="public_at" class="custom-radiobox" :value="true" v-model="public_at" />
                            <span>공개</span>
                          </label>
                          <label class="radio-label">
                            <input type="radio" name="public_at" class="custom-radiobox" :value="false" v-model="public_at" />
                            <span>비공개</span>
                          </label>
                        </div>
                      </td>
                    </tr>
                    <tr>
                      <th>설명</th>
                      <td>
                        <textarea class="content-box" cols="30" rows="35" v-model="customComment" @input="customComment = $event.target.value"></textarea>
                      </td>
                    </tr>
                  </table>
                </div>
                <!-- 레이아웃 및 컴포넌트 탭 -->
                <div class="content-box flex justify-between tab-box" v-show="activeTab === 'viewSetting'">
                  <div class="content-list layout flex50">
                    <div class="layout-tree content-box">
                      <div class="content-titleZone">
                        <div class="flex justify-between align-center">
                          <p class="box-title">레이아웃 및 컴포넌트</p>
                          <div>
                            <button id="horizontal-btn" @click="addSplitterLayout('horizontal')" title="수직레이아웃">
                              <img :src="verticalImg" />
                            </button>
                            <button id="vertical-btn" @click="addSplitterLayout('vertical')" title="수평레이아웃">
                              <img :src="horizontalImg" />
                            </button>
                            <button id="split-delete-btn" @click="deleteSplitterLayout" title="삭제">
                              <svg-icon type="mdi" :path="trashPath" :color="'#aaa'" />
                            </button>
                            <button class="attribute-btn" @click="fnAttributeToggle">
                              <svg-icon type="mdi" :path="dotPath" :color="'#aaa'" />
                              <div class="attribute-modal" v-show="isAttributeOpen">
                                <ul>
                                  <li class="flex align-center">
                                    <svg-icon type="mdi" :path="tablePath" />
                                    <p class="ml5">테이블 추가</p>
                                  </li>
                                  <li class="flex align-center">
                                    <svg-icon type="mdi" :path="chartPath" />
                                    <p class="ml5">차트 추가</p>
                                  </li>
                                </ul>
                              </div>
                            </button>
                          </div>
                        </div>
                      </div>
                      <ul>
                        <TreeItem :splitInfo="splitInfo" :selectLayout="currentLayout" @onChange="fnSelectLayout" />
                      </ul>
                    </div>
                  </div>
                  <div class="layout-option flex-column flex50">
                    <div v-if="!$isEmpty(currentLayout)">
                      <div class="tabnav3">
                        <ul class="flex justify-start align-center">
                          <template v-for="(item, idx) of optionList" :key="idx">
                            <li class="cursor" v-show="item.useAt" @click="fnChangeTab('opt', item.id)">
                              <p :class="{ activeOption: activeOption === item.id }">{{ item.name }}</p>
                            </li>
                          </template>
                        </ul>
                      </div>
                      <div v-if="activeOption === 'LAYOUT'">
                        <StyleSheet :styleSheet="currentLayout.styleSheet" />
                      </div>
                      <div v-if="activeOption === 'TITLE'">
                        <div class="table-zone">
                          <p class="object-title mb5">타이틀 사용 여부</p>
                          <div class="input-container flex">
                            <label class="radio-label">
                              <input type="radio" name="titleUseAt" class="custom-radiobox" :value="true" v-model="isUseSj" @change="fnChangeUseSj">
                              <span>사용</span>
                            </label>
                            <label class="radio-label">
                              <input type="radio" name="titleUseAt" class="custom-radiobox" :value="false" v-model="isUseSj" @change="fnChangeUseSj">
                              <span>미사용</span>
                            </label>
                          </div>
                          <div v-if="currentLayout.useSj">
                            <div>
                              <p class="object-title mb5">메인타이틀</p>
                              <input type="text" class="full-input" v-model="currentLayout.layoutSj.main_sj" />
                              <FontOption :fontStyle="currentLayout.layoutSj.styleSheetMain.fontStyle" :title="'메인'" />
                            </div>
                            <div>
                              <p class="object-title mb5">서브타이틀</p>
                              <input type="text" class="full-input" v-model="currentLayout.layoutSj.sub_sj" />
                              <FontOption :fontStyle="currentLayout.layoutSj.styleSheetSub.fontStyle" :title="'서브'" />
                            </div>
                          </div>
                        </div>
                      </div>
                      <div v-if="activeOption === 'COMPONENT'">
                        <StyleSheet :styleSheet="currentLayout.styleSheet" />
                      </div>
                    </div>
                  </div>
                </div>
                <!-- 데이터탭 -->
                <div class="content-box tab-box" v-show="activeTab === 'dataset'">
                  <div class="data-set" style="border-bottom: 1px solid #ddd">
                    <div class="content-box flex-column pd10">
                      <div class="content-titleZone">
                        <div class="flex justify-between align-center">
                          <p class="box-title">데이터 목록</p>
                          <button type="button" class="blue-border-btn small-btn" @click="fnCreateJobGroup">데이터 추가</button>
                        </div>
                      </div>
                      <div class="data-list">
                        <div v-for="(item, idx) of jobGroupList" :key="idx" @click="fnSelectJobGroup(item)">
                          <div :class="{
                            'item flex justify-between align-center': true,
                            mb5: idx < jobGroupList.length - 1,
                            selectData: item.group_nm == currentJobGroup.group_nm,
                          }">
                            <p class="flex align-center">
                              <svg-icon type="mdi" class="mr5" :width="20" :height="20" :path="dataPath" />
                              <span>{{ item.group_nm }}</span>
                            </p>
                            <div>
                              <button class="blue-border-btn set-btn" @click.stop="" @click="fnModalOpen(item, idx)">설정</button>
                              <button class="red-border-btn set-btn" @click.stop="" @click="deleteDiagram(item)">삭제</button>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                  <!-- 컬럼 정보 -->
                  <div class="column-list flex no-gutter">
                    <div class="content-box flex50 pd10" style="border-right: 1px solid #ddd">
                      <div class="flex100 content-box">
                        <p class="box-title mb10">컬럼정보</p>
                        <div class="overflow-y" style="height: calc(100% - 22px)">
                          <template v-if="currentDataTable.columnDatas.length > 0">
                            <div v-for="(column, idx) of this.currentDataTable.columnDatas" :key="idx" :class="{
                              item: true,
                              mb5: idx < currentDataTable.columnDatas.length - 1,
                            }" draggable="true" @dragstart="startDrag(column)">
                              <p>
                                <b>{{ column.displyColumnNm }}</b> ({{ column.columnNm }}) : [{{ column.dataTy }}]
                              </p>
                            </div>
                          </template>
                          <div v-else>
                            <p style="font-size: 1.3rem"> 컬럼 데이터가 존재하지 않습니다. </p>
                          </div>
                        </div>
                      </div>
                    </div>
                    <div class="content-box flex50">
                      <div class="content-box flex-column no-gutter pd10 overflow-y">
                        <div class="flex30 mb10">
                          <div class="editor-box content-box pd10">
                            <p class="object-title mb5">항목(Category)</p>
                            <div class="overflow-y" style="height: calc(100% - 22px)" @drop.prevent="onDrop('xdata')" @dragenter.prevent @dragover.prevent>
                              <template v-if="dataX.length > 0">
                                <div v-for="(column, indx) of dataX" :key="indx" :class="{
                                  'item flex justify-between align-center': true,
                                  mb5: idx < dataX.length - 1,
                                }">
                                  <p> {{ column.displyColumnNm }} : [{{ column.dataTy }}] </p>
                                  <div>
                                    <button class="red-border-btn set-btn" @click="deleteItem(column, 'x')"> 삭제 </button>
                                  </div>
                                </div>
                              </template>
                              <div class="item mb5" v-else>
                                <p>NO_DATA</p>
                              </div>
                            </div>
                          </div>
                        </div>
                        <div class="flex40 mb10">
                          <div class="editor-box content-box pd10">
                            <div class="flex justify-between align-center">
                              <p class="object-title mb5">값(Value)</p>
                              <select v-model="currentCalc" @change="fnChangeCalc">
                                <option v-for="(item, idx) of calcList" :key="idx" :value="item.key">{{ item.value }}</option>
                              </select>
                            </div>
                            <div class="overflow-y" style="height: calc(100% - 22px)" @drop.prevent="onDrop('ydata')" @dragenter.prevent @dragover.prevent>
                              <template v-if="dataY.length > 0">
                                <div v-for="(column, indx) of dataY" :key="indx" :class="{
                                  'item flex justify-between align-center': true,
                                  mb5: idx < dataY.length - 1,
                                }">
                                  <p> {{ column.displyColumnNm }} : [{{ column.dataTy }}] </p>
                                  <button class="red-border-btn set-btn" @click="deleteItem(column, 'y')"> 삭제 </button>
                                </div>
                              </template>
                              <div class="item mb5" v-else>
                                <p>NO_DATA</p>
                              </div>
                            </div>
                          </div>
                        </div>
                        <div class="flex20 mb10">
                          <div class="editor-box content-box pd10">
                            <p class="object-title mb5">다음으로 색상 지정</p>
                            <ul class="overflow-y" style="height: calc(100% - 16px)">
                              <li class="item mb5">
                                <p>column</p>
                              </li>
                            </ul>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <div class="content-box flex justify-between tab-box" v-show="activeTab === 'component'">
                  <div class="content-box overflow-y">
                    <ul class="flex justify-center">
                      <li v-for="(cmpnt, idx) in chartComponent" :key="idx" class="flex5 mt10 cursor" @click="
                        fnCreateComponent(idx, cmpnt.type, cmpnt.id, cmpnt.name)
                        ">
                        <div :class="{
                          'img-wrap border': true,
                          active: this.activeIndex === idx,
                        }">
                          <img :src="cmpnt.src" alt="" />
                          <div class="img-hover">
                            <span>{{ cmpnt.name }}</span>
                          </div>
                        </div>
                      </li>
                    </ul>
                  </div>
                </div>
              </div>
              <button class="custom-toggle" :style="isTabZoneOpen ? { right: '-25px' } : { right: '-24px' }" @click="fnTabZoneToggle">
                <svg-icon type="mdi" :path="arrowPath" :color="'#333'" />
              </button>
            </div>
            <!-- 미리보기  -->
            <div :class="{
              'preview-zone': true,
              flex100: isTabZoneOpen,
              flex70: !isTabZoneOpen,
            }">
              <div id="splitter-container" ref="splitterContainer" :class="{
                'splitter-panel-custom pl10': true,
                active: clickElement === 'splitter-container',
              }">
                <SplitterLayout :splitInfo="splitInfo" :selectLayout="currentLayout" @onChange="fnSelectLayout" />
              </div>
              <div class="flex justify-end" id="buttonZone">
                <button class="blue-btn small-btn" @click="fnInsert">
                  <span v-if="!pageId">등록</span>
                  <span v-else>수정</span>
                </button>
                <button class="blue-border-btn small-btn" @click="fnInit"> 초기화 </button>
                <button class="darkg-btn small-btn" @click="fnGotoList">취소</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- 잡그룹관리 모달 -->
  <div class="modal-wrapper" v-if="isModalOpen">
    <div class="modal-container">
      <div class="modal-title flex justify-between align-center">
        <h2>잡그룹 관리</h2>
        <button class="close-btn" @click="fnModalClose">
          <svg-icon type="mdi" :width="20" :height="20" :path="closePath" />
        </button>
      </div>
      <div class="modal-content-monthly mb10">
        <JobGroupManagement :jobGroup="currentJobGroup" />
      </div>
      <div class="modal-end flex justify-end">
        <button class="blue-btn small-btn" @click="fnSaveJobGroup"> 저장 </button>
        <button class="blue-border-btn small-btn" @click="fnModalClose"> 취소 </button>
      </div>
    </div>
  </div>
</template>
<script>
import _ from "lodash";
import axios from "axios";
// icon
import SvgIcon from "@jamescoyle/vue-icon";
import {
  mdiChevronLeft,
  mdiChevronRight,
  mdiLandPlots,
  mdiRhombusSplit,
  mdiDatabaseCogOutline,
  mdiInformationSlabCircleOutline,
  mdiDotsVertical,
  mdiTableLarge,
  mdiChartLine,
  mdiDatabase,
  mdiTrashCanOutline,
  mdiClose,
} from "@mdi/js";
import SplitterLayout from "../../component/SplitterLayout.vue";
import TreeItem from "../../component/treeMenu/LayoutTree.vue";
import StyleSheet from "../../component/style/StyleSheetComponent.vue";
import BackgroundOption from "../../component/style/BackgroundOption.vue";
import CellOption from "../../component/style/CellOption.vue";
import FontOption from "../../component/style/FontOption.vue";
import chartDataTransform from "../../component/chart/chartDataTransform.js";
import html2canvas from "html2canvas";
import DataComponent from "../../component/flowComponent/DataComponent.vue";
import JobGroupManagement from "../../component/flowComponent/JobGroupManagement.vue";

export default {
  components: {
    SvgIcon,
    SplitterLayout,
    TreeItem,
    BackgroundOption,
    CellOption,
    FontOption,
    StyleSheet,
    DataComponent,
    JobGroupManagement,
  },

  data() {
    return {
      isLoading: true,
      // icon
      closePath: mdiClose,
      arrowPath: mdiChevronLeft,
      dotPath: mdiDotsVertical,
      tablePath: mdiTableLarge,
      chartPath: mdiChartLine,
      dataPath: mdiDatabase,
      trashPath: mdiTrashCanOutline,

      horizontalImg: require("../../../resources/img/icon/hor_b.png"),
      verticalImg: require("../../../resources/img/icon/ver_b.png"),

      navList: [
        { id: "pageInfo", name: "페이지 정보", iconPath: mdiInformationSlabCircleOutline, },
        { id: "viewSetting", name: "레이아웃", iconPath: mdiLandPlots },
        { id: "component", name: "컴포넌트", iconPath: mdiRhombusSplit },
        { id: "dataset", name: "데이터", iconPath: mdiDatabaseCogOutline },
      ],
      optionList: [],
      chartComponent: [
        {
          src: require("../../../resources/img/chartIcon/column_chart_v.png"),
          type: "chart",
          id: "column_chart_v",
          name: "세로형 막대 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/column_chart_h.png"),
          type: "chart",
          id: "column_chart_h",
          name: "가로형 막대 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/clustered_chart_v.png"),
          type: "chart",
          id: "clustered_chart_v",
          name: "세로형 클러스터 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/clustered_chart_h.png"),
          type: "chart",
          id: "clustered_chart_h",
          name: "가로형 클러스터 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/stacked_bar_chart.png"),
          type: "chart",
          id: "stacked_bar_chart",
          name: "적층 막대 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/line_chart.png"),
          type: "chart",
          id: "line_chart",
          name: "선 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/mix_chart.png"),
          type: "chart",
          id: "mix_chart",
          name: "혼합 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/pie_chart.png"),
          type: "chart",
          id: "pie_chart",
          name: "파이 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/dounet_chart.png"),
          type: "chart",
          id: "dounet_chart",
          name: "도넛 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/semicircle_chart.png"),
          type: "chart",
          id: "semicircle_chart",
          name: "반원 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/bubble_chart.png"),
          type: "chart",
          id: "bubble_chart",
          name: "버블 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/word_chart.png"),
          type: "chart",
          id: "word_chart",
          name: "단어 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/stacked_column_chart.png"),
          type: "chart",
          id: "stacked_column_chart",
          name: "세로형 적층 막대 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/node_line_chart.png"),
          type: "chart",
          id: "node_line_chart",
          name: "노드 라인 차트",
        },
        {
          src: require("../../../resources/img/chartIcon/liin_chart_back.png"),
          type: "chart",
          id: "liin_chart_back",
          name: "라인 백그라운드 차트",
        },
      ],
      calcList: [
        { key: "default", value: "기본" },
        { key: "sum", value: "합계" },
        { key: "avg", value: "평균" },
        { key: "min", value: "최솟값" },
        { key: "max", value: "최댓값" },
      ],

      pageId: this.$route.query.page_id,

      isModalOpen: false,
      isTabZoneOpen: false,
      isAttributeOpen: false,
      isUseSj: false,

      activeTab: "pageInfo",
      activeOption: "LAYOUT",

      // 페이지정보 탭
      customTitle: null, // 제목
      public_at: true, // 공개여부
      customComment: null, // 설명

      activeIndex: null,

      originSplitInfo: {},
      splitInfo: _.cloneDeep(this.$getDefaultJobGroup().customSplitter),
      jobGroupList: [],

      // 현재 작업 객체
      currentLayout: {},
      currentJobGroup: Object.assign({}, this.$getDefaultObject().jobGroup),
      currentJobGroupIdx: null,
      currentCalc: "default",
      currentDataTable: Object.assign({}, this.$getDefaultObject().dataTable),

      dragData: {},
      dataX: [],
      dataY: [],
    };
  },

  created() {
    this.activeTab = "pageInfo";

    if (this.$isEmpty(this.pageId)) {
      this.init();
      this.isLoading = false;
    } else {
      this.getCustomData(); // 기존 데이터 가져오기
    }
  },

  computed: {},

  watch: {
    // 컴포넌트 사용 여부
    'currentLayout.component'(newVal, oldVal) {
      if (!this.$isEmpty(newVal)) {
        this.currentLayout.se = 'component'
      }
    },
  },

  methods: {
    // 초기화
    async init() {
      this.activeIndex = null;

      // 페이지 정보 초기화
      this.customTitle = null;
      this.customComment = null;
      this.public_at = true;

      // 레이아웃 초기화
      let splitInfo = _.cloneDeep(this.$getDefaultJobGroup().customSplitter);
      splitInfo.se = "splitter";
      splitInfo.depth = 0;
      splitInfo.layout_nm = "LAY_" + this.generateShortUUID();
      splitInfo.position_idx = 1;
      splitInfo.styleSheet.borderStyle = Object.assign({}, this.$getDefaultJobGroup().borderStyle);
      splitInfo.styleSheet.background_style = Object.assign({}, this.$getDefaultJobGroup().background_style);
      this.splitInfo = splitInfo;
      this.fnSelectLayout(splitInfo); // 레이아웃 선택

      // 데이터 초기화
      this.jobGroupList = [];
    },

    // 현재 컬럼 정보 초기화
    initColumnInfo() {
      // 현재 데이터테이블 변경
      if (this.currentJobGroup.jobItms.length === 0) {
        this.currentDataTable = Object.assign({}, this.$getDefaultObject().dataTable);
      } else {
        const index = this.currentJobGroup.jobItms.length - 1;
        this.currentDataTable = this.currentJobGroup.jobItms[index].dataTable;
      }

      // 컬럼 정보 초기화
      this.dragData = {};
      this.dataX = [];
      this.dataY = [];
      this.currentCalc = "default";

      // 컴포넌트가 있는 경우 컴포넌트 데이터 초기화
      let component = this.currentLayout.component;
      if (component != null) {
        component.component_itm.dataTable = this.currentJobGroup.dataTable;
        component.component_itm.data_list = [];
        component.jobInfo[0] = this.currentJobGroup;
      }
    },

    // 기존 데이터 가져오기
    getCustomData() {
      const vm = this;
      axios({
        url: "/custom/customPageOneDataselect/" + vm.pageId,
        method: "get",
        headers: { "Content-Type": "application/json; charset=UTF-8" },
      })
        .then((response) => {
          // 페이지정보
          let resPageInfo = response.data.resultData.pageInfo;
          vm.customTitle = resPageInfo.ttl;
          vm.customComment = resPageInfo.cn;
          vm.public_at = resPageInfo.public_at;

          // 레이아웃
          vm.splitInfo = response.data.resultData.splitterInfo;
          this.fnSelectLayout(vm.splitInfo); // 레이아웃 선택

          // 데이터 목록
          vm.jobGroupList = response.data.resultData.jobGroupList;

          let originData = {
            customTitle: resPageInfo.ttl,
            customComment: resPageInfo.cn,
            public_at: resPageInfo.public_at,
            splitInfo: response.data.resultData.splitterInfo,
            jobGroupList: response.data.resultData.jobGroupList,
          }
          vm.originSplitInfo = _.cloneDeep(originData);

          this.isLoading = false;
        })
        .catch((error) => {
          vm.$showAlert("오류", "데이터 현황관리 차트 연결 오류, 관리자에게 문의하세요.");
          vm.$router.push({ path: "/customSelectList.page" });
        });
    },

    // 현재 탭 변경
    fnChangeTab(type, value) {
      if (type == "nav") {
        this.activeTab = value;
      } else if (type == "opt") {
        this.activeOption = value;
      }
    },

    // 탭설정패널 여닫기 버튼 동작
    fnTabZoneToggle() {
      this.isTabZoneOpen = !this.isTabZoneOpen;

      // 아이콘 변경
      if (this.isTabZoneOpen) {
        this.arrowPath = mdiChevronRight;
      } else {
        this.arrowPath = mdiChevronLeft;
      }
    },

    // 레이아웃 및 컴포넌트 더보기 버튼 동작
    fnAttributeToggle() {
      this.isAttributeOpen = !this.isAttributeOpen;
    },

    // 타이틀 사용 여부
    async fnChangeUseSj() {
      const isCheck = await this.$showConfirm("경고", "타이틀 사용 여부 변경 시 작업 중인 데이터가 삭제됩니다.<br>타이틀을 사용 여부를 변경 하시겠습니까?");
      if (isCheck) {
        this.currentLayout.useSj = this.isUseSj;
        this.currentLayout.se = 'splitter';

        if (this.currentLayout.useSj) {
          this.currentLayout.component = null; // 컴포넌트 초기화

          // 현재 레이아웃에 따른 레이아웃 탭 옵션
          this.optionList = [
            { id: "LAYOUT", name: "레이아웃", useAt: true },
            { id: "TITLE", name: "타이틀", useAt: this.currentLayout.children.length == 0 },
            { id: "COMPONENT", name: "컴포넌트", useAt: !this.$isEmpty(this.currentLayout.component) },
          ];
        } else {
          this.currentLayout.layoutSj = _.cloneDeep(this.$getDefaultObject().layoutSj); // 타이틀 초기화
        }
      } else {
        this.isUseSj = this.currentLayout.useSj;
      }
    },

    // 유효성 검사 - 컴포넌트 추가
    validationByCreateComponent(id) {
      if (id == "bubble_chart") {
        this.$showAlert("메세지", "현재 지원하지 않는 컴포넌트입니다.");
        return true;
      }

      if (this.currentLayout == null) {
        this.$showAlert("메세지", "컴포넌트를 추가할 레이아웃을 먼저 선택해 주세요.");
        return true;
      }

      if (this.currentLayout.children.length > 0) {
        this.$showAlert("메세지", "선택된 레이아웃이 분할되어 있습니다.<br>선택된 레이아웃 내부를 하나로 합치거나 다른 레이아웃을 선택해 주세요.");
        return true;
      }

      return false;
    },

    // 컴포넌트 추가
    async fnCreateComponent(index, type, id, name) {
      // 유효성 검사
      if (this.validationByCreateComponent(id)) {
        return;
      };

      let message;
      if (this.currentLayout.component == null) {
        message = name + " 컴포넌트를 추가하시겠습니까?";
      } else {
        message = "선택된 레이아웃이 비어있지 않아, 컴포넌트를 변경할 경우 모든 데이터가 초기화됩니다.<br>선택한 컴포넌트로 덮어쓰기 하시겠습니까?";
      }

      let isCheck = await this.$showConfirm("메세지", message);
      if (!isCheck) {
        return;
      }
      this.activeIndex = index;

      let chartData = _.cloneDeep(this.$getDefaultJobGroup().componentData);
      chartData.chart_knd = id;
      chartData.component_nm = "ChartCmmn";
      chartData.component_type = type;

      let component = _.cloneDeep(this.$getDefaultJobGroup().component);
      component.component_itm = chartData;

      this.currentLayout.se = "component";
      this.currentLayout.component = component;

      this.currentJobGroup = Object.assign({}, this.$getDefaultObject().jobGroup);
      this.initColumnInfo(); // 현재 컬럼 정보 초기화
    },

    // 레이아웃 선택
    fnSelectLayout(layout) {
      // 현재 레이아웃 변경
      this.currentLayout = layout;

      // 현재 레이아웃에 따른 레이아웃 탭 옵션
      this.optionList = [
        { id: "LAYOUT", name: "레이아웃", useAt: true },
        { id: "TITLE", name: "타이틀", useAt: layout.children.length == 0 },
        { id: "COMPONENT", name: "컴포넌트", useAt: !this.$isEmpty(layout.component) },
      ];
      this.fnChangeTab("opt", "LAYOUT"); // 탭 변경

      // 현재 레이아웃에 컴포넌트가 있는 경우
      this.activeIndex = null; // 초기화
      let component = layout.component;
      if (component != null) {
        // 컴포넌트 선택
        for (let i = 0; i < this.chartComponent.length; i++) {
          if (this.chartComponent[i].id === component.component_itm.chart_knd) {
            this.activeIndex = i;
            break;
          }
        }

        // 컬럼 정보 변경
        this.dataX = component.component_itm.categoryAxis;
        this.dataY = component.component_itm.valueAxis;
        this.currentCalc = component.component_itm.chart_cal;

        // 현재 잡그룹 변경
        if (component.jobInfo.length > 0) {
          this.currentJobGroup = component.jobInfo[0];

          // 현재 데이터테이블 변경
          if (this.currentJobGroup.jobItms.length > 0) {
            const index = this.currentJobGroup.jobItms.length - 1;
            this.currentDataTable = this.currentJobGroup.jobItms[index].dataTable;
          } else {
            this.currentDataTable = Object.assign({}, this.$getDefaultObject().dataTable);
          }
          return;
        }
      }

      this.currentJobGroup = Object.assign({}, this.$getDefaultObject().jobGroup);
      this.initColumnInfo(); // 현재 컬럼 정보 초기화
    },

    findLoop(item) {
      if (item.se == this.currentLayout.se) {
        item = this.currentLayout;
        return;
      } else {
        for (let next of item.children) {
          this.findLoop(next);
        }
      }
    },

    // 레이아웃 추가
    async addSplitterLayout(type) {
      // 유효성 검사
      if (this.currentLayout.layout_nm == null) {
        this.$showAlert("메세지", "선택된 레이아웃이 없습니다.");
        return;
      }

      let isCheck = await this.$showConfirm("메세지", "선택된 레이아웃을 분할하시겠습니까?");
      if (!isCheck) {
        return;
      }

      let copy = _.cloneDeep(this.currentLayout);
      copy.parents_splitter_id = this.currentLayout.layout_nm;
      copy.depth = this.currentLayout.depth + 1;
      copy.indx = 0;
      copy.layout_nm = "LAY_" + this.generateShortUUID();

      let newItem = _.cloneDeep(this.$getDefaultJobGroup().customSplitter);
      newItem.se = "splitter";
      newItem.parents_splitter_id = this.currentLayout.layout_nm;
      newItem.depth = this.currentLayout.depth + 1;
      newItem.indx = 1;
      newItem.layout_nm = "LAY_" + this.generateShortUUID();
      newItem.styleSheet.borderStyle = _.cloneDeep(this.$getDefaultJobGroup().borderStyle);
      newItem.styleSheet.background_style = _.cloneDeep(this.$getDefaultJobGroup().background_style);

      this.currentLayout.se = "splitter";
      this.currentLayout.useSj = false;
      this.currentLayout.layoutSj = Object.assign({}, this.$getDefaultJobGroup.layoutSj);
      this.currentLayout.layout_type = type;
      this.currentLayout.layout_size1 = 50;
      this.currentLayout.layout_size2 = 50;

      this.currentLayout.component = null;

      this.currentLayout.children = [];
      this.currentLayout.children.push(copy);
      this.currentLayout.children.push(newItem);
    },

    // 등록-수정
    fnInsert() {
      let vm = this;

      // 유효성 검사
      if (vm.$isEmpty(vm.customTitle)) {
        vm.$showAlert("메세지", "제목은 필수입력입니다.");
        return;
      }
      if (vm.splitInfo.component == null && vm.splitInfo.children.length == 0) {
        vm.$showAlert("메세지", "레이아웃 또는 차트를 추가해야합니다.");
        return;
      }

      let customPageVO = {
        ttl: vm.customTitle,
        cn: vm.customComment,
        splitInfo: vm.splitInfo,
        public_at: vm.public_at,
        jobFlow: { jobGroup: vm.jobGroupList },
      }

      let url = "/custom/insert";
      if (!vm.pageId) {
        customPageVO["wrt_id"] = this.$store.state.loginUser.user_id;
      } else {
        url = "/custom/customUpdate";
        customPageVO["page_id"] = vm.pageId;
        customPageVO["mdfcn_id"] = this.$store.state.loginUser.user_id;
      }

      // 캡처할 요소
      let element = vm.$refs.splitterContainer;
      html2canvas(element).then((canvas) => {
        canvas.toBlob(function (blob) {
          let formData = new FormData();
          formData.append("img", blob, "capture.png");
          formData.append("customPage", JSON.stringify(customPageVO));

          axios({
            url: url,
            method: "post",
            headers: { "Content-Type": "multipart/form-data; charset=UTF-8" },
            data: formData,
          })
            .then((response) => {
              if (response.data.checkMessage.success) {
                const successMsg = vm.pageId ? "페이지 수정에 성공하였습니다." : "페이지 등록에 성공하였습니다.";
                vm.$showAlert("메세지", successMsg);
                const pageId = vm.pageId || response.data.resultData.pageId;
                vm.$router.push({
                  path: "/customSelectOne.page",
                  query: { page_id: pageId },
                });
              } else {
                const failMsg = vm.pageId ? "수정에 실패하였습니다." : "등록에 실패하였습니다.";
                vm.$showAlert("메세지", failMsg);
              }
            })
            .catch((error) => {
              if (error.response && error.response.data && error.response.data.code == "COMPONENT_DATA_NOT_FOUND") {
                vm.$showAlert("메세지", "데이터를 추가하지 않은 컴포넌트가 존재합니다.");
              } else {
                vm.$showAlert("메세지", "요청 처리 중 오류가 발생했습니다.");
              }
            });
        });
      });
    },

    // 아이디 만들기
    generateShortUUID() {
      const fullUUID = crypto.randomUUID();
      return fullUUID.replace(/-/g, '').substring(0, 8);
    },

    // 초기화 버튼 동작
    async fnInit() {
      let isCheck = await this.$showConfirm("초기화", "초기화 하시겠습니까? 데이터가 모두 삭제됩니다.");
      if (isCheck) {
        if (this.$isEmpty(this.pageId)) {
          this.init();
        } else {
          // 페이지정보
          this.customTitle = this.originSplitInfo.customTitle;
          this.customComment = this.originSplitInfo.customComment;
          this.public_at = this.originSplitInfo.public_at;

          // 레이아웃
          this.splitInfo = this.originSplitInfo.splitInfo;
          this.fnSelectLayout(this.splitInfo); // 레이아웃 선택

          // 데이터 목록
          this.jobGroupList = this.originSplitInfo.jobGroupList;
        }
      }
    },

    // 컬럼정보 비우기
    fnInitColInfo() {
      this.currentJobGroup = Object.assign({}, this.$getDefaultObject().jobGroup);
      this.initColumnInfo(); // 현재 컬럼 정보 초기화
    },

    // 레이아웃 삭제
    async deleteSplitterLayout() {
      if (!this.currentLayout.layout_nm) {
        this.$showAlert("메세지", "삭제할 레이아웃이 없습니다.");
        return;
      }

      if (this.currentLayout.layout_nm == this.splitInfo.layout_nm) {
        this.$showAlert("메세지", "최상위 레이아웃은 삭제할 수 없습니다.");
        return;
      }

      let isCheck = await this.$showConfirm(
        "레이아웃 삭제",
        "선택한 레이아웃을 삭제하시겠습니까?"
      );
      if (!isCheck) {
        return;
      }

      let parentLayout = this.findParentLayout(this.splitInfo, this.currentLayout.parents_splitter_id);

      if (parentLayout.children.length > 0) {
        let copy = _.cloneDeep(parentLayout.children.filter((item) => item !== this.currentLayout));

        if (copy.length == 1) {
          parentLayout.se = copy[0].se;
          parentLayout.type = copy[0].type;
          parentLayout.min_width = copy[0].min_width;
          parentLayout.min_height = copy[0].min_height;
          parentLayout.layout_size1 = copy[0].layout_size1;
          parentLayout.layout_size2 = copy[0].layout_size2;
          parentLayout.layout_type = copy[0].layout_type;
          parentLayout.styleSheet = copy[0].styleSheet;
          parentLayout.children = copy[0].children;
          parentLayout.component = copy[0].component;
          parentLayout.active = copy[0].active;
          parentLayout.layoutSj = copy[0].layoutSj;
          parentLayout.sizes = copy[0].sizes;
          parentLayout.useSj = copy[0].useSj;

          return;
        }
      }

      parentLayout.children = parentLayout.children.filter((item) => item !== this.currentLayout);
    },

    // 부모 요소 검색
    findParentLayout(layout, parentId) {
      let result = null;
      if (layout.layout_nm === parentId) {
        result = layout;
      } else {
        if (layout.children.length > 0) {
          for (let child of layout.children) {
            result = this.findParentLayout(child, parentId);
            if (result != null) {
              break;
            }
          }
        }
      }
      return result;
    },

    // 취소 (데이터활용관리 목록으로 이동)
    async fnGotoList() {
      let isCheck = await this.$showConfirm("경고", "취소할 경우 작성 중인 내용이 사라집니다.<br>취소하시겠습니까?");
      if (isCheck) {
        this.$router.push({ path: "/customSelectList.page" });
      }
    },

    // 잡그룹 추가
    async fnCreateJobGroup() {
      let component = this.currentLayout.component;
      if (component != null) {
        if (!this.$isEmpty(component.component_itm.data_list)) {
          let isCheck = await this.$showConfirm("경고", "컴포넌트 컬럼 설정 후, 새 데이터를 추가할 경우 기존 정보가 삭제됩니다.<br>새 데이터를 추가하시겠습니까?");
          if (!isCheck) {
            return;
          }
        }
      }

      let jobGroup = Object.assign({}, this.$getDefaultObject().jobGroup);
      jobGroup.group_nm = "데이터" + (this.jobGroupList.length + 1);
      this.jobGroupList.push(jobGroup);
      this.currentJobGroup = jobGroup;
      this.initColumnInfo(); // 현재 컬럼 정보 초기화
    },

    // 잡그룹 선택
    async fnSelectJobGroup(jobGroup) {
      let component = this.currentLayout.component;
      if (component != null) {
        if (jobGroup.jobItms.length > 0) {
          let index = jobGroup.jobItms.length - 1;
          if (component.component_itm.dataTable == jobGroup.jobItms[index].dataTable) {
            return;
          }
        }
        if (!this.$isEmpty(component.component_itm.data_list)) {
          let isCheck = await this.$showConfirm("경고", "컴포넌트 컬럼 설정 후, 다른 데이터를 선택할 경우 기존 정보가 삭제됩니다.<br>다른 데이터를 선택하시겠습니까?");
          if (!isCheck) {
            return;
          }
        }
      }

      this.currentJobGroup = jobGroup;
      this.initColumnInfo(); // 현재 컬럼 정보 초기화
    },

    // 잡그룹관리 모달 열기
    fnModalOpen(jobGroup, idx) {
      this.currentJobGroup = _.cloneDeep(jobGroup);
      this.currentJobGroupIdx = idx;
      this.isModalOpen = true;
    },

    // 잡그룹관리 모달 닫기
    fnModalClose() {
      this.isModalOpen = false;
    },

    // 잡그룹관리 저장
    fnSaveJobGroup() {
      this.jobGroupList[this.currentJobGroupIdx] = this.currentJobGroup;
      this.fnSelectJobGroup(this.currentJobGroup); // 잡그룹 선택 (저장한 정보 선택)
      this.fnModalClose(); // 노드설정 모달 닫기
    },

    // 드래그 이벤트
    startDrag(data) {
      this.dragData = data;
    },

    // 값 계산법 변경
    fnChangeCalc() {
      this.currentLayout.component.component_itm.chart_cal = this.currentCalc;
      this.onChangeChartData(); // 차트 데이터 수정
    },

    // 드랍 이벤트
    async onDrop(type) {
      // 레이아웃인 경우 경고 후 실행 취소
      if (this.currentLayout.children.length > 0) {
        this.$showAlert("경고", "레이아웃은 설정할 수 없습니다.");
        return;
      }

      // 컴포넌트가 설정되지 않은 경우 경고 후 실행 취소
      if (this.$isEmpty(this.currentLayout.component)) {
        this.$showAlert("경고", "컴포넌트 등록 후 설정할 수 있습니다.");
        return;
      }

      if (type == "xdata") {
        if (this.dataX.length > 0) {
          let isCheck = await this.$showConfirm(
            "경고",
            "데이터를 변경하시겠습니까?"
          );
          if (!isCheck) {
            return;
          }
        }
        this.dataX = []; // 초기화
        this.dataX.push(this.dragData);
        this.currentLayout.component.component_itm.categoryAxis = this.dataX;
      } else if (type == "ydata") {
        if (this.dragData.dataTy === "STRING") {
          this.$showAlert(
            "메세지",
            "값(Value)에는 숫자 데이터만 사용 가능합니다."
          );
          return;
        }
        this.dataY.push(this.dragData);
        this.currentLayout.component.component_itm.valueAxis = this.dataY;
      }

      this.onChangeChartData(); // 차트 데이터 수정
    },

    // 차트 데이터 수정
    onChangeChartData() {
      let dataList = chartDataTransform.createData(
        this.currentDataTable,
        this.currentLayout.component.component_itm.categoryAxis,
        this.currentLayout.component.component_itm.valueAxis,
        "null",
        this.currentLayout.component.component_itm.chart_cal
      );
      this.currentLayout.component.component_itm.data_list = dataList;
      this.currentLayout.component.jobInfo[0] = this.currentJobGroup;
    },

    // 아이템 삭제
    deleteItem(column, category) {
      if (category == "x") {
        for (let i = 0; i < this.dataX.length; i++) {
          if (this.dataX[i].orginlColumnNm == column.orginlColumnNm) {
            this.dataX.splice(i, 1);
          }
        }
      } else if (category == "y") {
        for (let i = 0; i < this.dataY.length; i++) {
          if (this.dataY[i].orginlColumnNm == column.orginlColumnNm) {
            this.dataY.splice(i, 1);
          }
        }
      }
    },

    // 잡그룹 삭제
    async deleteDiagram(item) {
      let isCheck = await this.$showConfirm(
        "삭제",
        "선택한 데이터를 삭제하시겠습니까?\n관련된 데이터도 함께 삭제됩니다."
      );
      if (!isCheck) {
        return;
      }

      // splitInfo에 적용했던 데이터가 있는지 확인하여 삭제 (재귀)
      if (this.splitInfo.children.length > 0) {
        this.RecursiveFunc(this.splitInfo.children, item);
      }

      if (this.splitInfo.component != null) {
        if (this.splitInfo.component.jobInfo[0].group_nm == item.group_nm) {
          this.splitInfo.component = null;
          this.splitInfo.se = "splitter";
        }
      }

      this.jobGroupList = this.jobGroupList.filter(
        (jobItem) => jobItem !== item
      );

      this.currentJobGroup = Object.assign({}, this.$getDefaultObject().jobGroup);
      this.initColumnInfo(); // 현재 컬럼 정보 초기화
    },

    // 재귀함수
    RecursiveFunc(children, item) {
      for (let i = 0; i < children.length; i++) {
        if (children[i].children.length > 0) {
          this.RecursiveFunc(children[i].children, item);
        } else {
          if (children[i].component != null) {
            // children[i].jobInfo 와 item이 같은지 확인하여 삭제
            if (children[i].component.jobInfo[0].group_nm == item.group_nm) {
              children[i].component = null;
              children[i].se = "splitter";
            }
          }
        }
      }
    },
  },
};
</script>
<style scoped>
#splitter-container {
  width: 100%;
  height: calc(100% - 50px);
  margin-bottom: 20px;
}

#SplitterLayout {
  width: 100%;
  height: 100%;
}

#splitter-container.active {
  border: 3px dotted red;
}

.padding-1 {
  padding: 1rem;
}

#customComment {
  height: 99px;
}

.table-padding {
  padding: 15px 0;
}

.paletteLi {
  display: inline-block;
  margin-right: 10px;
}

.img-wrap {
  position: relative;
}

.img-wrap:hover .img-hover {
  display: flex;
}

.img-wrap .img-hover {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #213f9999;
  display: none;
  align-items: center;
  justify-content: center;
}

.img-wrap .img-hover span {
  padding: 10px;
  text-align: center;
  font-size: 1.5em;
  color: #ffffff;
  word-break: keep-all;
}

.selectData {
  border: solid 2px #5d5c5c;
  color: #ffffff;
  background-color: #ff9e29;
}
</style>