<template>
  <grid
    ref="tuiGrid"
    :class="addClass"
    :data="gridProps.data"
    :columns="gridProps.columns"
    :options="gridProps.options"
    :language="gridProps.language"
    @click="clicked"
    @response="response"
    @beforeRequest="beforeRequest"
    :summary="gridProps.summary"
  />
  <!--
    - 공식홈: https://ui.toast.com/tui-grid
    - vue git: https://github.com/nhn/toast-ui.vue-grid
    - api & sample: https://nhn.github.io/tui.grid/latest/
    - 연동 결과는 아래 포맷에 맞추어 주세요. 
      TuiGrid.java VO 참고
      적용 예: UserController > user
      {
        "result": true,
        "data": {
          "contents": [],
          "pagination": {
            "page": 1,
            "totalCount": 100
          }
        }
      }
  -->
</template>

<script>
import 'tui-grid/dist/tui-grid.css';
import 'tui-pagination/dist/tui-pagination.css';
import TuiGrid from 'tui-grid';
import { Grid } from '@toast-ui/vue-grid';

export default {
  name: 'tuiGrid',
  props: [
    'url', // 연동 url
    'initialRequest', // false일 시 초기 렌더링 시 백엔드에 요청 하지 않음. 이 경우 readData를 호출하여 그리드 데이터를 할당해 줘야 함
    'rowHeaders', // 체크 박스 등 헤더에 필요한 타입 ex) ["checkbox"]
    'header', // 옵션 (헤더 병합 등)
    'minRowHeight', // 리스트 row 높이
    'minBodyHeight', // 테이블 높이
    'pagination', // 페이지 네비게이션 사용 여부
    'perPage', // 페이지 당 개수
    'totalItems', // 부모창에 표시할 총 컨텐츠 개수 변수 명 (더 좋은 방법 있으면 알려주세요.)
    'columns', // 컬럼 정보
    'showVerticalBorder', // cell 세로라인 표시
    'noDataStr', // 데이터가 없을 때
    'noSearchStr', // 검색 결과가 없을 때
    'scrollX', // 가로 스크롤 사용 여부
    'scrollY', // 세로 스크롤 사용 여부
    'addClass', // table에 추가할 클래스
    'evtClick', // 클릭 이벤트 정보, 해당 커럼을 클릭하면 callback 수행, 이때 해당 row의 데이터를 파라미터로 반환한다. Object Or Array
    // ex) evtClick: { column: "idx", callback: clickIdx }
    //     or  evtClick: [ { column: "idx", callback: this.myFnc }, { column: "name", ...  } ]
    'summary'
  ],
  components: {
    grid: Grid
  },
  data() {
    return {
      instance: null,
      gridProps: null,
      currEventListener: null,
      currGridEle: null,
      currMode: 'normal'
    };
  },
  mounted() {
    this.saveGridEventListner();
    //if(this.currMode != 'normal')
    //this.initGridEventListner();
  },
  beforeDestroy() {
    this.addGridEventListner();
  },
  created() {
    /**
     * Use the static method as below
     */
    TuiGrid.applyTheme('default', {
      outline: {
        border: '#333 !important' // 테이블 위아래 선의 색깔 지정
      },
      row: {
        hover: {
          background: '#fafafa !important' // row 마우스 오버 시 색깔 지정
        }
      },
      area: {
        header: {
          border: '#aaaaaa !important' // header 아래 선의 색깔 지정
        }
      },
      cell: {
        normal: {
          showVerticalBorder: this.showVerticalBorder === true // 각 셀의 세로 선 노출
        }
      }
    });

    this.gridProps = {
      data: {
        api: {
          readData: { url: this.url, method: 'GET' }
        },
        initialRequest: typeof this.initialRequest == 'undefined' ? true : this.initialRequest
      },
      options: {
        rowHeaders: this.rowHeaders,
        header: this.header ? this.header : { height: 47 },
        minRowHeight: this.minRowHeight ? this.minRowHeight : 56,
        minBodyHeight: this.minBodyHeight ? this.minBodyHeight : 56,
        showDummyRows: true,
        scrollX: this.scrollX === true,
        scrollY: this.scrollY === true,
        pagination: this.pagination,
        pageOptions: {
          perPage: this.perPage
        }
      },
      language: {
        name: 'ko',
        value: {
          display: {
            noData: this.noDataStr
          }
        }
      },
      columns: this.columns,
      summary: this.summary
    };
  },
  methods: {
    clicked: function(v) {
      if (typeof this.evtClick != 'undefined' && this.evtClick != null) {
        let data = this.$refs.tuiGrid.invoke('getRow', v.rowKey);

        if (Array.isArray(this.evtClick)) {
          for (var i = 0; i < this.evtClick.length; i++) {
            if (v.columnName == this.evtClick[i].column && typeof this.evtClick[i].callback == 'function') {
              this.evtClick[i].callback(data);
            }
          }
        } else if (
          this.evtClick.column != null &&
          v.columnName == this.evtClick.column &&
          typeof this.evtClick.callback == 'function'
        ) {
          this.evtClick.callback(data);
        }
      }
    },
    response: function(event) {
      let xhr = event.xhr;
      let statusCode = xhr.status;
      if (statusCode == 200) {
        let respData = JSON.parse(xhr.response).data;
        this.$parent[this.totalItems] = respData.pagination.totalCount;

        let len = respData.contents.length;
        if (this.scrollY == false) {
          if (len > 0) {
            let divLen = 6;
            if (this.scrollX == true) {
              divLen = 5;
            }
            // header의 height를 구할 수 있는 방법은? 일단 48
            let addLen = len / divLen;
            this.getGridInstance().setBodyHeight((len + addLen) * 48);
          } else {
            this.getGridInstance().setBodyHeight(48);
          }
        }
      } else if (statusCode == 401 || statusCode == 418) {
        // alert('세션이 만료되었습니다.');
        window.top.location.href = '/login';
      } else {
        window.top.location.href = '/view/error/' + statusCode;
      }
    },
    beforeRequest: function(event) {
      if (this.scrollY == false) {
        this.getGridInstance().setBodyHeight(90);
      }
    },
    getData: function() {
      // 전체 Row 데이터를 가져온다.
      return this.getGridInstance().getData();
    },
    getRow: function(rowKey) {
      // 해당 Row의 데이터를 가져온다.
      return this.getGridInstance().getRow(rowKey);
    },
    getPagination: function() {
      // 페이지 정보
      return this.getGridInstance().getPagination();
    },
    setPerPage: function(count) {
      // 페이지 당 표시 개수 변경
      this.getGridInstance().setPerPage(count);
    },
    readData: function(page, param) {
      // 페이지 데이터 갱신 (initialRequest가 false일 경우 초기 데이터 로드시에도 사용)
      this.getGridInstance().readData(page, param, true);
    },
    appendRow: function(rowData, rownum) {
      var optionsOpt = {
        at: rownum || 0,
        extendPrevRowSpan: false,
        focus: false
      };
      this.getGridInstance().appendRow(rowData, optionsOpt);
    },
    search: function(param) {
      // 검색 결과가 없을 경우 텍스트 변경
      let noSearchStr = '';
      if (typeof this.noSearchStr == 'undefined') {
        noSearchStr = '검색 결과가 없습니다.';
      }
      this.$refs.tuiGrid.language.value.display.noData = noSearchStr;
      this.$refs.tuiGrid.setLanguage();

      // param을 기반으로 리스트 갱신
      this.readData(1, param);
    },
    gridMethod: function(params) {
      return this.$refs.tuiGrid.invoke(...params);
    },
    getGridInstance() {
      if (this.instance == null) {
        this.instance = this.$refs.tuiGrid.gridInstance;
      }
      return this.instance;
    },
    saveGridEventListner() {
      // this.currGridEle = document.querySelector(`div.tui-grid-container.tui-grid-show-lside-area`);
      this.currGridEle = document.querySelector(`div.tui-grid-container`);

      if (this.currGridEle != null && window.getEventListeners(this.currGridEle).mousedown) {
        this.currEventListener = window.getEventListeners(this.currGridEle).mousedown[0].listener;
      }
    },
    removeGridEventListner() {
      this.currMode = 'edit';
      this.currGridEle.removeEventListener('mousedown', this.currEventListener);
      this.currGridEle.setAttribute('tabindex', '0');
      this.currGridEle.style.outline = 'none';
      this.currGridEle.addEventListener('keydown', this.copyEvent, false);
    },
    addGridEventListner() {
      this.currMode = 'normal';
      this.currGridEle.removeAttribute('tabindex');
      this.currGridEle.removeEventListener('keydown', this.copyEvent);
      this.currGridEle.addEventListener('mousedown', this.currEventListener);
    },
    initGridEventListner() {
      document.querySelector(`div.tui-grid-container`).removeAttribute('tabindex');
      document.querySelector(`div.tui-grid-container`).removeEventListener('keydown', this.copyEvent);
      document.querySelector(`div.tui-grid-container`).addEventListener('mousedown', this.currEventListener);
    },
    copyEvent(ev) {
      ev = ev || window.event;
      var key = ev.which || ev.keyCode; // keyCode detection
      var ctrl = ev.ctrlKey ? ev.ctrlKey : key === 17 ? true : false; // ctrl detection

      if (key == 67 && ctrl) {
        var clipboard = document.querySelector('.tui-grid-clipboard');
        clipboard.innerHTML = this.getGridInstance().getFocusedCell().value;
        clipboard.focus();
        document.execCommand('copy');
      }
    }
  }
};
</script>

<!-- 스타일 추가 시 CSS 우선순위를 높이기 위해 아래과 같이 .tui-grid-cell를 CSS 선택자에 포함시켜서 사용해야 적용 됨 -->
<style>
.tui-grid-cell.cell-red {
  background-color: red;
}
.tui-grid-table {
  width: 100% !important;
}
</style>
