<template>
  <div :style="pageStyle">
    <q-card
      v-if="showSearchPanel"
      style="margin-bottom: 15px;"
    >
      <q-resize-observable @resize="onSearchPanelResize"></q-resize-observable>
      <q-card-main>
        <slot name="search-form"></slot>
      </q-card-main>
      <q-card-actions align="center">
        <div class="w3-container">
          <q-btn
            color="primary"
            @click="searchOk"
            :label="$t('sys.search')"
            style="min-width:80px;"
          ></q-btn>
          <q-btn
            color="secondary"
            v-if="showDownloadBtn"
            @click="downloadCsv"
            :label="$t('sys.export')"
            style="min-width:80px;"
          ></q-btn>
          <slot name="search-panel-actions"></slot>
        </div>
      </q-card-actions>
    </q-card>
    <q-modal
      position="top"
      no-backdrop-dismiss
      no-esc-dismiss
      v-model="searchOpened"
    >
      <div style="min-width:300px;min-height:100px;">
        <div class="w3-padding">
          <slot name="search-form"></slot>
        </div>
        <div class="w3-padding w3-center">
          <q-btn
            color="primary"
            @click="searchOk"
            :label="$t('sys.search')"
            style="width:100px;"
          ></q-btn>
          <q-btn
            color="secondary"
            @click="searchCancel"
            :label="$t('sys.cancel')"
            style="width:100px;"
          ></q-btn>
        </div>
      </div>
    </q-modal>
    <div>
      <q-search
        v-if="showSearchFieldWithMobile"
        v-model="filter"
        clearable
      ></q-search>
    </div>
    <q-modal
      no-esc-dismiss
      no-backdrop-dismiss
      v-model="isShowColumnsUsersSetting"
    >
      <div style="overflow-y: hidden;">
        <div style="color:#fff;background-color:#334048;text-align: center;font-size:18pt;padding: 5px;">{{ $t("sys.column").toUpperCase() }}</div>
        <!--螢幕高度80%-->
        <div :style="{'overflow-y': 'auto','min-height':'min-content','max-height':columnsSettingHeight}">
          <q-list
            separator
            link
          >
            <q-item
              v-for="(itm,idx) in columnsTemp"
              :key="itm.name"
              :class="currentColumnName == itm['name'] ? 'w3-khaki' : ''"
            >
              <q-item-side><q-toggle v-model="columnsTemp[idx].$$users_setting_is_show"></q-toggle></q-item-side>
              <q-item-main :label="itm.label"></q-item-main>
              <q-item-side>
                <q-btn
                  dense
                  icon="arrow_upward"
                  color="blue"
                  @click="columnsMoveUpDown(idx,itm['name'],'up')"
                ></q-btn>
                &nbsp;
                <q-btn
                  dense
                  icon="arrow_downward"
                  color="red"
                  @click="columnsMoveUpDown(idx,itm['name'],'down')"
                ></q-btn>
              </q-item-side>
            </q-item>
          </q-list>
        </div>
        <div class="w3-center w3-padding">
          <q-btn
            :label="$t('sys.ok')"
            color="primary"
            @click="doColumnsUsersSetting"
            style="width:70px;"
          ></q-btn>
          <q-btn
            :label="$t('sys.cancel')"
            color="secondary"
            @click="openColumnsUsersSetting(false)"
            style="width:70px;"
          ></q-btn>
          <q-btn
            :label="$t('sys.default')"
            color="orange"
            @click="initColumnsDefault(true)"
            style="width:70px;"
          ></q-btn>
        </div>
      </div>
    </q-modal>
    <q-table
      :title="title"
      :data="data"
      :filter="filter"
      :columns="columnsList"
      :row-key="rowKey"
      :pagination.sync="pagination"
      :selection="selection"
      :selected.sync="selfSelected"
      :rows-per-page-options="rowsPerPageOptions"
    >
      <template slot="top-right">
        <div v-if="!showSearchFieldWithMobile && showSearchField">
          <q-search
            v-model="filter"
            clearable
          ></q-search>
        </div>
        <q-btn
          v-if="showUsersSettingBtn"
          color="primaty"
          flat
          round
          dense
          icon="settings"
          @click="openColumnsUsersSetting(true)"
        >
        </q-btn>
      </template>
      <q-tr
        slot="body"
        slot-scope="props"
        :props="props"
        @click.native="rowClick(props,event)"
      >
        <q-td
          auto-width
          class="text-center"
          v-if="selection=='multiple' || selection=='single'"
        >
          <q-checkbox
            color="primary"
            v-model="props.selected"
          ></q-checkbox>
        </q-td>
        <q-td
          v-for="col in props.cols"
          :key="col.name"
          :props="props"
        >
          <slot
            v-if="col.$$is_slot"
            :name="'row_col_'+col.name"
            :row_data="props"
          ></slot>
          <div
            v-else-if="col.$$is_num_format"
            v-text="$root.FnFormatNumber(col.value,col.$$num_format_decimal)"
          ></div>
          <div
            v-else-if="col.$$is_date_format"
            v-text="moment(col.value).format('YYYY/MM/DD')"
          ></div>
          <div
            v-else-if="col.$$is_datetime_format"
            v-text="moment(col.value).format('YYYY/MM/DD HH:mm:ss')"
          ></div>
          <div
            v-else
            v-text="col.value"
          ></div>
        </q-td>
        <q-td
          style="width:10px;"
          align="center"
        >
          <slot
            name="row-control"
            :row_data="props"
          ></slot>
        </q-td>
      </q-tr>
    </q-table>
    <q-page-sticky
      position="top-right"
      :offset="[10, 10]"
    >
      <!-- 預設有一個 search button //-->
      <q-btn
        round
        v-if="showSearchBtn"
        color="primary"
        @click="searchOpened=true"
        icon="search"
      ></q-btn>
      <q-btn
        round
        v-if="showSearchBtn && showDownloadBtn"
        color="primary"
        @click="downloadCsv"
        icon="download"
      ></q-btn>
      <slot name="page-sticky">
      </slot>
    </q-page-sticky>
  </div>
</template>

<script>
module.exports = {
  name: "data-table",
  props: {
    "title": {
      "type": "String",
    },
    "offset-screen-height": { // 微調螢幕的長度, 因為要算每頁筆數, 本元件可能有配合父頁版面調整大小
      "type": "Number",
      "default": -150,
    },
    "show-search-btn": { // 是否顯示查詢按鈕
      "type": "Boolean",
      "default": false
    },
    "show-search-panel": { // 是否顯示查詢面版
      "type": "Boolean",
      "default": false
    },
    "show-download-btn": { // 是否顯示下載按鈕
      "type": "Boolean",
      "default": false
    },
    "show-search-field": { // 是否顯示slot top-left 的查詢欄位
      "type": "Boolean",
      "default": false
    },
    "show-users-setting-btn": { // 是否顯示slot top-left 的欄位設定按鈕
      "type": "Boolean",
      "default": true,
    },
    'rows-num': { // 一頁要幾筆
      default: 0
    },
    "outfilter": { // 來自外部的過濾
      "default": ""
    },
    "selection": {
      "type": "String" // 是否出現checkbox選單(原quasar功能), single:單選, multiple:多選
    },
    "selected": { // 回傳選擇記錄後的值給父層, 父層需使用.sync修飾詞 <data-table :selected.sync="xxx" />
      "type": "Array",
      "default": []
    },
    "row-key": { // 表格資料的主key
      "default": "__index"
    },
    "columns": { // 欄位清單
      "type": "Array",
      "default": []
    },
    "data": { // 資料清單
      "type": "Array",
      "default": []
    },
    "page-style": { // 放在頁面 template / div 的 style
      "type": "String",
      "default": "",
    }
  },
  data () {
    return {
      "filter": "",
      "pagination": { rowsPerPage: 10 },
      "searchOpened": false,
      "searchPanelHeight": 0,
      "columnsData": [], // 由page傳入後,可能會再經過修改顯示與順序等功能, 所以要另外存一份(若不存另一份,toggle無法填值到props)
      "columnsTemp": [], // 在設定時的暫存資料(要確定後才會寫入columsData)
      "columnsDb": [], // 從db取得的欄位設定資料
      "isShowColumnsUsersSetting": false, // 開啟欄位設定的視窗
      "currentColumnName": "", // 目前操作的欄位索引
    }
  },
  computed: {
    isDesktop () { // 是否為桌面平台
      return this.$root.VarIsDesktop;
    },
    isMobile () { // 是否為手機平台
      return this.$root.VarIsMobile;
    },
    isTablet () { // 是否為平板平台
      return this.$root.VarIsTablet;
    },
    isMenuOpen () { // 是否開啟選單
      return this.$root.VarIsMenuOpen;
    },
    screenIsVertical () { // 螢幕是否直立
      return this.$root.VarScreenIsVertical;
    },
    showSearchFieldWithMobile () { // 是否顯示查詢框, 加上 mobile 判斷
      return this.showSearchField && ((this.isMobile && this.screenIsVertical) || (this.isTablet && this.isMenuOpen));
    },
    layoutScreenHeight () { // 螢幕的高
      return this.$root.VarLayoutScreenHeight;
    },
    layoutContainerHeight () { // 螢幕的寬
      return this.$root.VarLayoutContainerHeight;
    },
    rowsPerPage () { // 每頁顯示幾筆, 會根據螢幕高度與平台計算
      var newNum = 0;
      if (this.rowsNum > 0) {
        newNum = this.rowsNum
      } else {
        var screenHeightNow = this.layoutScreenHeight + this.offsetScreenHeight;
        if (this.isMobile && this.screenIsVertical) { // 手機 & 垂直
          newNum = Math.round((screenHeightNow - this.searchPanelHeight) / 70)
        } else if (this.isMobile) {
          newNum = Math.round(screenHeightNow / 120)
        } else if (this.isTablet && this.screenIsVertical) { // 平板 & 垂直
          newNum = Math.round((screenHeightNow - this.searchPanelHeight) / 70)
          // } else if (this.isTablet && this.isMenuOpen) { // 沒效, 有空再找原因
          //   return Math.round(this.layoutContainerHeight / 60) - 2
        } else if (this.isTablet) {
          newNum = Math.round(screenHeightNow / 100)
        } else { // 桌面
          newNum = Math.round((screenHeightNow - this.searchPanelHeight) / 70)
        }
      }
      return newNum
    },
    rowsPerPageOptions () { // 每頁筆數選單
      if (this.isPhone) {
        return _.uniq([Math.round(this.rowsPerPage), 0])
      } else {
        return _.uniq([Math.round(this.rowsPerPage), 5, 10, 20, 30, 0])
      }
    },
    selfSelected: { // 選擇哪些row
      get () {
        return this.selected
      },
      set (val) {
        this.$emit('update:selected', val) // 為了讓父層 :selected.sync 生效
      }
    },
    columnsList () { // 介面與匯出csv用的欄位清單
      return _.filter(this.columnsData, (itm) => {
        return itm.$$users_setting_is_show;
      });
    },
    columnsSettingHeight () { // 欄位設定視窗的清單的高度
      if (this.isMobile) {
        return "60vh";
      } else {
        return "600px";
      }
    },
    columnsDataMapIdx () { // 將 columnsData 轉成 map {欄位名稱:索引值}, 方便取用
      return _.reduce(this.columnsData, (result, value, idx) => {
        result[value.name] = idx;
        return result;
      }, {})
    }
  },
  watch: {
    layoutScreenHeight () { // 當螢幕高度變更時(如:水平與垂值切換), 會變更rowsPerPage,所以要選擇該頁
      this.pagination.rowsPerPage = this.rowsPerPage;
    },
    searchPanelHeight () { // 當search panel 高度變更時, 會變更rowsPerPage,所以要選擇該頁
      if (this.showSearchPanel) {
        this.pagination.rowsPerPage = this.rowsPerPage;
      }
    },
    outfilter (nv) {
      this.filter = nv
    },
    columns (nv) {
      _.each(nv, (itm) => { // 為了切換語系(因為由columns轉成columnsData無法直接切換,需在此撰寫watch處理)
        this.columnsData[this.columnsDataMapIdx[itm["name"]]].label = itm["label"];
      });
      /*if (this.showUsersSettingBtn) {
        this.loadColumnsSetting();
      } else {
        this.initColumnsDefault();
      }*/
    }
  },
  mounted () {
    this.pagination.rowsPerPage = this.rowsPerPage;
    this.filter = this.outfilter;
    if (this.showUsersSettingBtn) {
      this.loadColumnsSetting();
    } else {
      this.initColumnsDefault();
    }
  },
  methods: {
    rowClick (props, evt) {
      this.$emit("row-click", props, evt);
    },
    searchOk (evt) { // 查詢確認送出事件
      this.$emit("search-ok", evt);
      this.searchOpened = false;
    },
    searchCancel (evt) { // 取消查詢送出事件
      this.$emit("search-cancel", evt);
      this.searchOpened = false;
    },
    downloadCsv () { // 下載csv
      this.$root.FnReportDownload("csv", this.data, this.columnsList);
    },
    initColumnsDefault (isTemp) { // 從 page 傳入的 columns 初始化欄位資料
      if (!isTemp) {
        this.columnsData = [];
      } else {
        this.columnsTemp = [];
      }
      _.each(this.columns, (itm) => {
        if (!_.isBoolean(itm.$$users_setting_is_show)) {
          itm.$$users_setting_is_show = true;
        }
        if (!isTemp) {
          this.columnsData.push(_.cloneDeep(itm));
        } else {
          this.columnsTemp.push(_.cloneDeep(itm));
        }
      });
    },
    loadColumnsSetting () { // 從db取得欄位設定資料
      this.$root.FnWebAPIGet({
        "Action": "UsersSetting",
        "Datas": {
          "menu_page": this.$root.VarMenuPage,
        },
        "menu_page": "sys_component",
      }).then((res) => {
        if (res.data.result) {
          this.columnsDb = JSON.parse(res.data.data); // 資料庫儲存的是json字串
          if (!_.isEmpty(this.columnsDb) && this.columns.length == this.columnsDb.length) { // 若有資料庫的設定, 則使用資料庫的設定(若沒有設定,則為[]字陣列)
            let interList = _.intersectionWith(this.columns, this.columnsDb, (itm1, itm2) => {
              return itm1.name == itm2.name && itm1.field == itm2.field; // 比對目前最新欄位與資料庫儲存欄位是否相同
            });
            // 若資料庫的欄位設定與目前目前最新欄位, 則使用資料庫的設定
            // 若不相同, 代表程式的columns有更新, 則使用目前最新欄位
            if (interList.length == this.columns.length) {
              this.columnsData = [];
              _.each(this.columnsDb, (itm) => {
                let thisIdx = _.findIndex(this.columns, (v) => {
                  return v.name == itm.name;
                });
                let thisItm = _.cloneDeep(this.columns[thisIdx]);
                thisItm.$$users_setting_is_show = itm.$$users_setting_is_show;
                this.columnsData.push(thisItm);
              });
              return;
            } else {
              console.log("系統預設欄位與資料庫欄位設定不同, 使用系統預設欄位");
            }
          }
        }
        this.initColumnsDefault();
      }).catch(function (err) {
        console.log(err);
        this.initColumnsDefault();
      });;
    },
    onSearchPanelResize (props) {
      if (this.showSearchPanel) { // 若不顯示 search panel 則不需要取得它的高度
        this.searchPanelHeight = props.height;
      }
    },
    openColumnsUsersSetting (isOpen) { // 開啟欄位設定
      if (isOpen) {
        this.columnsTemp = _.cloneDeep(this.columnsData);
      }
      this.currentColumnName = "";
      this.isShowColumnsUsersSetting = isOpen;
    },
    doColumnsUsersSetting () { // 儲存欄位設定
      this.columnsData = _.cloneDeep(this.columnsTemp);
      this.isShowColumnsUsersSetting = false;
      this.$root.FnWebAPIPost({
        "Action": "UsersSetting",
        "Datas": {
          "menu_page": this.$root.VarMenuPage,
          "setting": this.columnsData,
        },
        "menu_page": "sys_component",
      });
    },
    columnsMoveUpDown (idx, name, direction) { // 移動欄位順序
      this.currentColumnName = name;
      if (direction == "up") {
        if (idx > 0) {
          this.columnsTemp.splice(idx - 1, 0, this.columnsTemp.splice(idx, 1)[0]);
        }
      } else {
        if (idx < this.columnsTemp.length - 1) {
          this.columnsTemp.splice(idx + 1, 0, this.columnsTemp.splice(idx, 1)[0]);
        }
      }
    },
  }
}
</script>

<style scoped>
.q-table-top {
  background-color: #334048;
  color: #fff;
  font-size: 13pt;
  padding-right: 5px;
}
.q-table-top .q-input-target,
.q-table-top .q-if {
  color: #fff;
  font-size: 13pt;
}
.q-select .q-input-target {
  width: 10px !important;
  font-size: 12pt;
}
.q-table > thead > tr > th {
  text-align: center !important;
}
th {
  font-size: 14pt;
  font-weight: bold;
  color: #287dd1;
}
td {
  font-size: 13pt !important;
}
</style>
