<template>
  <div class="container">
    <div class="page-titleZone flex justify-between align-center">
      <p class="main-title flex80">스케줄 관리</p>
    </div>
    <div class="content-wrap">
      <div class="content content-box flex-column no-gutter">
        <div class="row flex50">
          <div class="flex100">
            <div class="content-titleZone flex justify-between align-center">
              <p class="box-title">다이어그램 목록</p>
              <div class="search-bar flex justify-end align-center">
                <input
                  type="date"
                  name="start-date"
                  id="start-date"
                  class="square-date"
                  :class="{ 'date-placeholder': false }"
                  data-placeholder="날짜 선택"
                  v-model="search_date.value"
                />
                <span class="coupler">~</span>
                <input
                  type="date"
                  name="end-date"
                  id="end-date"
                  class="square-date ml5"
                  :class="{ 'date-placeholder': false }"
                  data-placeholder="날짜 선택"
                  v-model="search_date.value2"
                />
                <select class="square-select ml5" v-model="search_data1.value">
                  <option :value="null">상태</option>
                  <option value="run">진행</option>
                  <option value="stop">중단</option>
                </select>
                <select class="square-select ml5" v-model="search_data2.key">
                  <option :value="null">전체</option>
                  <option value="sj">제목</option>
                  <option value="creat_id">작성자</option>
                </select>
                <div class="search-square">
                  <input
                    type="text"
                    class="square-input"
                    placeholder="Search"
                    v-model="search_data2.value"
                    v-on:keyup.enter="fnDiagramList()"
                  />
                  <button
                    class="square-button blue-btn"
                    @click="fnDiagramList()"
                  >
                    <svg-icon
                      type="mdi"
                      :path="this.$getIconPath()"
                      class="square-icon"
                    ></svg-icon>
                  </button>
                </div>
              </div>
            </div>
            <div class="table-zone">
              <table class="list-table">
                <colgroup>
                  <col style="width: 5%" />
                  <col style="width: 5%" />
                  <col style="width: 25%" />
                  <col style="width: 15%" />
                  <col style="width: 20%" />
                  <col style="width: 20%" />
                  <col style="width: 15%" />
                </colgroup>
                <thead>
                  <tr>
                    <th>
                      <input
                        type="checkbox"
                        v-model="isChkAll"
                        @change="fnChkAll()"
                      />
                    </th>
                    <th>번호</th>
                    <th>제목</th>
                    <th>작성자</th>
                    <th>반복주기</th>
                    <th>등록일</th>
                    <th>상태</th>
                  </tr>
                </thead>
                <tbody>
                  <template v-if="diagramList.length > 0">
                    <tr
                      v-for="(diagram, dataIndex) in diagramList"
                      :key="diagram"
                      @click="fnDiagramDetail(diagram.diagram_id)"
                    >
                      <td>
                        <input
                          type="checkbox"
                          :value="diagram"
                          v-model="selectedDiagramList"
                          @click.stop=""
                          @change="fnChangeCheckList"
                        />
                      </td>
                      <td>{{ dataIndex + 1 }}</td>
                      <td>{{ diagram.diagram_nm }}</td>
                      <td>{{ diagram.creat_id }}</td>
                      <td>{{ diagram.cron_chrctr }}</td>
                      <td>{{ $getFullTime(diagram.creat_dt) }}</td>
                      <td>
                        <div
                          v-if="diagram.schdul_sttus === 'run'"
                          class="flex justify-center align-center state green icon-area"
                        >
                          <svg-icon
                            type="mdi"
                            :width="21"
                            :height="21"
                            :path="checkPath"
                            class="mr5"
                          ></svg-icon>
                          <span>진행</span>
                        </div>
                        <div
                          v-else-if="diagram.schdul_sttus === 'stop'"
                          class="flex justify-center align-center state red"
                        >
                          <svg-icon
                            type="mdi"
                            :width="21"
                            :height="21"
                            :path="xPath"
                            class="mr5"
                          ></svg-icon>
                          <span>중단</span>
                        </div>
                      </td>
                    </tr>
                  </template>
                  <tr v-else>
                    <td colspan="7">등록된 데이터가 없습니다.</td>
                  </tr>
                </tbody>
              </table>
            </div>
            <div class="flex justify-end">
              <button
                class="blue-border-btn small-btn"
                @click="fnChkSttus('run')"
              >
                선택 실행
              </button>
              <button
                class="blue-border-btn small-btn"
                @click="fnChkSttus('stop')"
              >
                선택 중단
              </button>
              <button class="red-border-btn small-btn" @click="fnChkDel()">
                선택 삭제
              </button>
            </div>
            <PaginationButton
              v-model:currentPage="search.currentPage"
              :perPage="search.perPage"
              :totalCount="search.totalRows"
              :maxRange="5"
              :click="fnDiagramList"
            />
          </div>
        </div>
        <div class="row flex50">
          <div class="flex justify-between align-start content-box">
            <div class="flex30 content-box">
              <div class="left-content border flex100">
                <div class="content-titleZone">
                  <p class="box-title">다이어그램 등록</p>
                </div>
                <ScheculerCreateComp
                  :schedule="schedule"
                  @get-edit-scheduling="getEditScheduling"
                />
                <div class="flex justify-end" id="buttonZone">
                  <button
                    class="blue-btn small-btn"
                    id="registerButton"
                    @click="fnDataInsert"
                  >
                    <span v-if="!isSelectedDiagram">등록</span>
                    <span v-else>수정</span>
                  </button>
                  <button
                    class="blue-border-btn small-btn"
                    id="resetButton"
                    @click="fnFormReset"
                  >
                    초기화
                  </button>
                </div>
              </div>
            </div>
            <div class="right-content flex70 form-box">
              <div class="node-zone flex70" style="height: 94%">
                <ScheduleLogManagement
                  v-if="isLogListView"
                  :diagram_id="diagram.diagram_id"
                />
                <VueFlowZone
                  v-else
                  :nodes="diagram.nodes"
                  :edges="diagram.edges"
                  @changeDiagram="changeDiagram"
                />
              </div>
              <div class="flex justify-end">
                <button
                  v-if="!isLogListView"
                  class="blue-border-btn small-btn"
                  @click="fnOpenAddModal"
                >
                  노드 추가
                </button>
                <button
                  v-if="!isLogListView && diagram.nodes.length > 1"
                  class="blue-border-btn small-btn"
                  @click="operatorNow"
                >
                  즉시계산
                </button>
                <button
                  v-if="!isLogListView"
                  class="blue-border-btn small-btn"
                  @click="resetNode"
                >
                  초기화
                </button>
                <button
                  v-if="isLogListView"
                  class="blue-btn small-btn"
                  @click="fnNodeFlowView"
                >
                  다이어그램 보기
                </button>
                <button
                  v-if="!isLogListView && diagram.nodes.length > 1"
                  class="blue-btn small-btn"
                  @click="fnLogListView"
                >
                  로그 보기
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- 노드 추가 모달 -->
  <div v-show="isAddModalOpen" class="modal-wrapper">
    <div class="modal-container small-modal">
      <div class="modal-title">
        <div class="flex justify-between align-center">
          <h2>추가할 노드 선택</h2>
          <button class="close-btn" @click="fnCloseAddModal">X</button>
        </div>
      </div>
      <div class="modal-content-monthly">
        <div class="justify-center aling-center">
          <select class="square-select full-select" v-model="selectItem">
            <option
              v-for="(nodeType, indexNTL) of nodeTypeList"
              :key="indexNTL"
              :value="nodeType.cmmnCode"
            >
              {{ nodeType.codeNm }}
            </option>
          </select>
        </div>
      </div>
      <div class="modal-end flex justify-end">
        <button class="blue-btn small-btn" @click="fnAddNodeCheckBtn">
          확인
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";
import SvgIcon from "@jamescoyle/vue-icon";
import { mdiMagnify } from "@mdi/js";
import { mdiCheckCircle, mdiCloseCircle } from "@mdi/js";
import DefaultSearchBar from "../../template/templateElement/DefaultSearchBar.vue";
import PaginationButton from "../../component/PaginationButton.vue";
import ScheculerCreateComp from "../../component/ScheculerCreateComp.vue";
// vueFlowZone
import VueFlowZone from "./VueFlowZone.vue";
import ScheduleLogManagement from "./ScheduleLogManagement.vue";
// vueFlowZone - btns
import DatabaseConnection from "../../component/connection/itm/databaseConnection.vue";
import apiConnection from "../../component/connection/itm/apiConnection.vue";
import datasetUpdate from "../../component/connection/itm/datasetUpdate.vue";
import fileSelectDiagram from "../../component/connection/itm/fileSelectDiagram.vue";
import DataFilter from "../../component/connection/itm/dataFilter.vue";

export default {
  components: {
    SvgIcon: SvgIcon,
    PaginationButton,
    DefaultSearchBar,
    ScheculerCreateComp,
    // vueFlowZone
    VueFlowZone,
    ScheduleLogManagement,
    // vueFlowZone - btns
    DatabaseConnection,
    apiConnection,
    datasetUpdate,
    fileSelectDiagram,
    DataFilter,
  },
  data() {
    return {
      // svg
      searchPath: mdiMagnify,
      checkPath: mdiCheckCircle,
      xPath: mdiCloseCircle,

      // 검색
      search: this.$getDefaultSerchVO(),
      search_date: this.$getDefaultSerchItem("creat_dt", "dates"),
      search_data1: this.$getDefaultSerchItem("schdul_sttus", "string"),
      search_data2: this.$getDefaultSerchItem(null, "string"),

      // default
      diagramList: [],
      diagram: {
        nodes: [],
        edges: [],
      },
      schedule: {},
      isSelectedDiagram: false,

      // 전체 선택 여부 (true:전체선택 / false:전체선택해제)
      isChkAll: false,
      selectedDiagramList: [], // 다이어그램 목록에서 선택한 다이어그램의 목록

      showRepeatSettings: true, // 반복주기
      logId: null, // 로그 페이지에서 넘어온 ID
      totalNode: null, // 총 노드 수
      repetselect: null, // 반복주기 타입

      // 노드 타입
      originalNodeTypeList: [],
      nodeTypeList: [],

      // 다이어그램 로그 화면 여부(true:열림/false:닫힘)
      isLogListView: false,

      // 노드 추가
      isAddModalOpen: false, // 노드 추가 모달 열림 여부(true:열림/false:닫힘)
      selectItem: "DB_READ", // 노드 추가값 (기본:DB_READ)

      // 노드 수정
      isSetupModalOpen: false, // 노드 설정 모달 열림 여부(true:열림/false:닫힘)
      selectNode: {}, // 선택된 노드
    };
  },
  mounted() {
    this.resetNode();
    this.fnDiagramList();
    this.fnSearchCommonCode();
  },
  methods: {
    //초기화 함수
    resetNode() {
      this.diagram.nodes = []; // 노드 목록 비우기
      this.diagram.edges = []; // 엣지 목록 비우기

      // 엔드 노드(datasetUpdate) 추가
      const node = Object.assign({}, this.$getDefaultJobGroup().node);
      node.id = Date.now().toString();
      node.node_id = node.id;
      node.label = "DATASET_UPDATE";
      node.node_name = "DATASET_UPDATE";
      node.node_type = "DATASET_UPDATE";
      node.itm = Object.assign({}, this.$getDefaultJobGroup().jobItemGroup);
      node.center_x = 1050;
      node.center_y = 25;
      node.position = {
        x: node.center_x,
        y: node.center_y,
      };
      this.diagram.nodes.push(node);
    },

    // 다이어그램 목록 조회
    fnDiagramList() {
      const vm = this;
      // 데이터 세팅
      let data = vm.search;
      data.searchObjectList = []; // 초기화
      data.searchObjectList.push(this.search_date);
      data.searchObjectList.push(this.search_data1);
      data.searchObjectList.push(this.search_data2);
      // 실행
      axios({
        url: "/diagram/diagramListRead",
        method: "post",
        headers: { "Content-Type": "application/json; charset=UTF-8" },
        data: data,
      })
        .then((response) => {
          vm.diagramList = response.data.resultData.diagramList;
          vm.search = response.data.resultData.searchVO;
        })
        .catch((error) => {
          this.$showAlert(
            "에러 발생",
            "에러가 발생했습니다. 관리자에게 문의해 주세요."
          );
        });
    },

    // 노드 타입 목록 조회
    async fnSearchCommonCode() {
      this.originalNodeTypeList = await this.$getCommonCode("NODE_ITEM");
      this.nodeTypeList = this.originalNodeTypeList;
    },

    // 다이어그램 전체 선택
    fnChkAll() {
      this.selectedDiagramList = []; // 초기화
      if (this.isChkAll) {
        this.selectedDiagramList = this.diagramList;
      }
    },
    // 다이어그램 선택 여부 변경 시
    fnChangeCheckList() {
      if (this.selectedDiagramList.length == this.diagramList.length) {
        this.isChkAll = true;
      } else {
        this.isChkAll = false;
      }
    },

    // 선택 실행, 중단 버튼
    fnChkSttus(schdul_sttus) {
      const vm = this;
      for (let schedule of this.selectedDiagramList) {
        axios({
          url:
            "/schedule/scheduleSttusChange/" +
            schedule.schdul_id +
            "/" +
            schdul_sttus,
          method: "get",
          headers: { "Content-Type": "application/json; charset=UTF-8" },
        })
          .then((response) => {
            vm.$showAlert("수정", "수정이 완료 되었습니다.");
            this.fnDiagramList(); // 전체 재조회
            this.isChkAll = false; // 체크 박스 리셋
            this.selectedDiagramList = [];
          })
          .catch((error) => {
            vm.$showAlert(
              "오류",
              "처리 중 오류가 발생했습니다. 관리자에게 문의바랍니다."
            );
          });
      }
    },
    // 선택 삭제 버튼
    fnChkDel() {
      const vm = this;
      for (let schedule of this.selectedDiagramList) {
        axios({
          url: "/schedule/deleteSchedule/" + schedule.schdul_id,
          method: "get",
          headers: { "Content-Type": "application/json; charset=UTF-8" },
        })
          .then((response) => {
            this.fnDiagramList(); // 전체 재조회
            this.isChkAll = false; // 체크 박스 리셋
            this.selectedDiagramList = [];
          })
          .catch((error) => {
            vm.$showAlert(
              "오류",
              "처리 중 오류가 발생했습니다. 관리자에게 문의바랍니다."
            );
          });
      }
    },

    // 다이어그램 상세 조회
    fnDiagramDetail(diagramId) {
      const vm = this;
      // 실행
      axios({
        url: "/diagram/diagramDetailRead/" + diagramId,
        method: "get",
        headers: { "Content-Type": "application/json; charset=UTF8" },
      })
        .then((response) => {
          vm.isSelectedDiagram = true;
          vm.schedule = response.data.resultData.diagramDetailDTO.schedule;
          let diagram = response.data.resultData.diagramDetailDTO.diagram;
          for (let node of diagram.nodes) {
            node.position = {};
            node.position.x = node.center_x;
            node.position.y = node.center_x;
          }
          for (let edge of diagram.edges) {
            edge.id = edge.edge_id;
          }
          vm.diagram = diagram;
        })
        .catch((error) => {
          vm.$showAlert(
            "오류",
            "처리 중 오류가 발생했습니다. 관리자에게 문의바랍니다."
          );
        });
    },

    // 노드 추가 버튼 (노드 추가 모달 열기)
    fnOpenAddModal() {
      this.nodeTypeList = this.originalNodeTypeList; // 초기화
      for (let node of this.diagram.nodes) {
        if (node["node_type"] == "DATASET_UPDATE") {
          this.nodeTypeList = this.nodeTypeList.filter(
            (nodeType) => nodeType.codeNm !== "DATASET_UPDATE"
          );
        }
      }
      this.isAddModalOpen = true;
    },
    // 노드 추가 모달 닫기
    fnCloseAddModal() {
      this.isAddModalOpen = false;
      this.selectItem = "DB_READ"; // 초기화
    },
    // 아이디 생성
    createId(number) {
      let id = Math.floor(Math.random() * number) + 1;
      return id.toString();
    },
    // 노드 추가
    fnAddNodeCheckBtn() {
      let node = Object.assign({}, this.$getDefaultJobGroup().node);
      node.id = Date.now().toString();
      node.node_id = node.id;
      node.label = this.selectItem;
      node.node_name = this.selectItem;
      node.node_type = this.selectItem;
      node.center_x = this.createId(500);
      node.center_y = this.createId(500);
      node.position = {
        x: node.center_x,
        y: node.center_y,
      };
      let tempData = JSON.parse(JSON.stringify(node));
      tempData.data = null;
      node.data = tempData;
      switch (this.selectItem) {
        case "DB_READ":
          node.itm = Object.assign({}, this.$getDefaultJobGroup().connectionDb);
          node.itm.type = "dbConnection";
          break;
        case "API_READ":
          node.itm = Object.assign(
            {},
            this.$getDefaultJobGroup().connectionApi
          );
          break;
        case "FILE_READ":
          node.itm = Object.assign({}, this.$getDefaultJobGroup().fileRead);
          break;
        case "DATASET_READ":
          node.itm = Object.assign({}, this.$getDefaultJobGroup().DatasetPost);
          break;
        case "DATA_FILTER":
          node.itm = Object.assign({}, this.$getDefaultJobGroup().dataFilter);
          break;
        case "EHOJO_READ":
          node.itm = Object.assign({}, this.$getDefaultJobGroup().connectionEhojo);
          break;
        case "DATASET_UPDATE":
          node.itm = Object.assign({}, this.$getDefaultJobGroup().jobItemGroup);
          break;
      }
      this.diagram.nodes.push(node);
      // 모달 닫기
      this.fnCloseAddModal();
    },

    // 다이어그램 유효성 검사
    fnValidation() {
      if (this.$isEmpty(this.schedule.sj)) {
        this.$showAlert("경고", "제목이 비어있습니다. 제목을 입력해 주세요.");
        return false;
      }
      // 엔드 노드에 연결된 노드가 없는 경우
      let endNodeCnt = 0;
      let endEdgeCnt = 0;
      for (let node of this.diagram.nodes) {
        if (node["node_type"] == "DATASET_UPDATE") {
          endNodeCnt++;
          for (let edge of this.diagram.edges) {
            if (edge.target == node.id) {
              endEdgeCnt++;
            }
          }
        }
      }
      if (endNodeCnt < 1) {
        this.$showAlert("오류 발생", "DATASET_UPDATE를 생성해 주세요.");
        return false;
      }
      if (endEdgeCnt < 1) {
        this.$showAlert("오류 발생", "DATASET_UPDATE에 노드를 연결해 주세요.");
        return false;
      }
      return true;
    },
    // 다이어그램 등록
    async fnDataInsert() {
      const vm = this;
      // 유효성 검사
      if (!this.fnValidation()) {
        return;
      }
      // 연결되지 않은 노드 삭제
      let emptyEdgeCnt = 0;
      let emptyEdgeNodeList = [];
      for (let node of vm.diagram.nodes) {
        let edgeCnt = 0;
        for (let edge of vm.diagram.edges) {
          if (node.id == edge.source || node.id == edge.target) {
            edgeCnt++;
          }
        }
        if (edgeCnt < 1) {
          emptyEdgeCnt++;
          emptyEdgeNodeList.push(node.id);
        }
      }
      if (emptyEdgeCnt > 0) {
        let isChecked = await vm.$showConfirm(
          "경고",
          "노드 전달 시, 연결되지 않은 노드는 삭제됩니다. 그래도 실행하시겠습니까?"
        );
        if (!isChecked) {
          return;
        } else {
          for (let emptyEdgeNode of emptyEdgeNodeList) {
            vm.diagram.nodes = vm.diagram.nodes.filter(
              (node) => node.id !== emptyEdgeNode
            );
          }
        }
      }
      // 데이터 세팅
      let schedule = vm.schedule;
      schedule.schdul_sttus = "run";
      let diagram = vm.diagram;
      for (let node of diagram.nodes) {
        node.position = {};
        node.position.x = node.center_x;
        node.position.y = node.center_x;
      }
      for (let edge of diagram.edges) {
        delete edge.id;
      }
      let url = null;
      let message = null;
      if (!vm.isSelectedDiagram) {
        url = "/diagram/dataInsert.json";
        message = "등록이 완료 되었습니다.";
      } else {
        url = "/diagram/dataEdit.json";
        message = "수정이 완료 되었습니다.";
      }
      // 실행
      axios({
        url: url,
        method: "post",
        headers: { "Content-Type": "application/json; charset=UTF-8" },
        data: {
          schedule: schedule,
          diagram: diagram,
        },
      })
        .then((response) => {
          vm.$showAlert("실행 결과", message);
          this.fnDiagramList(); // 전체 재조회
        })
        .catch((error) => {
          vm.$showAlert(
            "오류",
            "처리 중 오류가 발생했습니다. 관리자에게 문의바랍니다."
          );
        });
    },
    // 다이어그램 등록 폼 초기화
    fnFormReset() {
      this.schedule = {};
    },

    // 스케쥴 업데이트
    getEditScheduling(title, dc, getCronStr, getCron, isCyclical) {
      this.schedule.sj = title;
      this.schedule.dc = dc;
      this.schedule.cycle_at = isCyclical;
      this.schedule.cron = getCron;
      this.schedule.cron_chrctr = getCronStr;
    },

    //로그 페이지에서 ID를 가져온다
    dataDiagram() {
      this.logId = this.$route.query.receiveQuery;
      return this.logId;
    },

    // 즉시계산
    operatorNow() {
      const vm = this;
      // 데이터 세팅
      let data = vm.diagram;
      for (let edge of data.edges) {
        delete edge.id;
      }
      // 실행
      axios({
        url: "/diagram/operatorNow.json",
        method: "post",
        headers: {
          "Content-Type": "application/json; charset=UTF-8",
        },
        data: vm.diagram,
      })
        .then((response) => {
          vm.$showAlert("결과내용", "데이터셋 업데이트를 완료했습니다.");
        })
        .catch((error) => {
          vm.$showAlert(
            "오류",
            "처리 중 오류가 발생했습니다. 관리자에게 문의바랍니다."
          );
        });
    },

    // vueFlowZone 보기 변경 (log view 화면)
    fnLogListView() {
      this.isLogListView = true;
    },
    // vueFlowZone 보기 변경 (node flow 화면/디폴트)
    fnNodeFlowView() {
      this.isLogListView = false;
    },

    // 다이어그램 수정
    changeDiagram(nodes, edges) {
      this.diagram.nodes = nodes;
      this.diagram.edges = edges;
    },
  },
};
</script>