<template>
	<div>
		<!-- 标题区 -->
		<!-- 表格区 -->
		<ag-grid-vue
			class="table ag-theme-material"
			:class="`ag-theme-${theme}`"
			ref="grid"
			style="width: 100%;"
			:style="gridStyle"
			:gridOptions="gridOptions"
			@grid-ready="onGridReady"
			:enableCellChangeFlash="true"
			:columnDefs="formatedColumns"
			:rowData="rowData"
			:frameworkComponents="gridFrameworkComponents"
			:suppressPaginationPanel="true"
			:animateRows="true"
			:localeText="localeText"
			:context="context"
		></ag-grid-vue>
		<!-- 工具栏区 -->
		<div class="toolbox">
			<div class="tools-item toolbar">
				<ButtonGroup>
					<Button
						type="primary"
						size="small"
						icon="md-refresh"
						class="toolbar-item"
						ghost
						title="重载数据"
						v-show="tools.indexOf('refresh') > -1"
						@click="load()"
					></Button>
					<Button
						type="primary"
						size="small"
						icon="md-print"
						ghost
						title="打印"
						class="toolbar-item"
						v-show="tools.indexOf('print') > -1"
						@click="print"
					></Button>
					<Button
						type="primary"
						size="small"
						icon="ios-document-outline"
						ghost
						title="导出csv"
						class="toolbar-item"
						v-show="tools.indexOf('exportCsv') > -1"
						@click="exportCsv"
					></Button>
					<Button
						type="primary"
						size="small"
						icon="md-document"
						ghost
						title="导出excel"
						class="toolbar-item"
						v-show="tools.indexOf('exportExcel') > -1"
						@click="exportExcelModalShow"
					></Button>
					<Button
						type="primary"
						size="small"
						icon="md-search"
						ghost
						title="快速查询"
						class="toolbar-item"
						v-show="tools.indexOf('fastquery') > -1 && pagerOpts && pagerOpts.loadUrl"
						@click="fastQueryShow = true"
					></Button>
					<Button
						type="primary"
						size="small"
						icon="md-cog"
						ghost
						title="设置"
						class="toolbar-item"
						v-show="tools.indexOf('config') > -1"
						@click="configShow = true"
					></Button>
				</ButtonGroup>
			</div>
			<Page
				class="tools-item"
				v-if="pagerOpts"
				:current="pager.nowPage"
				:page-size="pager.pageSize"
				:total="pager.recordCount"
				show-elevator
				show-sizer
				show-total
				:page-size-opts="pageSizeOpts"
				transfer
				@on-change="pageChange"
				@on-page-size-change="pageSizeChange"
			/>
		</div>
		<FastQueryModal
			:columns="flatColumns"
			v-model="fastQueryShow"
			:dicts="dicts"
			:gridDicts="gridDicts"
			@on-search="onFastQuerySearch"
		></FastQueryModal>
		<!-- 导出csv -->
		<Modal v-model="exportModal" title="导出" width="432">
			<Form :model="exportConfig" label-position="right" ref="formData" :label-width="80">
				<FormItem label="模式">
					<RadioGroup v-model="exportConfig.state">
						<Radio label="0">全表</Radio>
						<Radio label="1">当前页</Radio>
					</RadioGroup>
				</FormItem>
				<FormItem label="条目上限" v-if="exportConfig.state==='0'">
					<Slider
						v-model="exportConfig.max"
						show-input
						:max="pager.recordCount?pager.recordCount:5000"
						style="width:100%;"
					></Slider>
				</FormItem>
			</Form>
			<div slot="footer">
				<Button type="default" @click="exportModal = false">关闭</Button>
				<Button type="primary" @click="exportExcel">导出</Button>
			</div>
		</Modal>
		<Spin fix v-show="loading" size="large">
			<Icon type="ios-loading" size="50" class="demo-spin-icon-load"></Icon>
			<div>加载中...</div>
		</Spin>
		<!-- 设置模态框 -->
		<Modal v-model="configShow" title="设置" footer-hide height="800">
			<Tree class="config-tree" :data="configData" @on-select-change="onConfigClick"></Tree>
		</Modal>
	</div>
</template>
<script>
// 基于ag-grid开发的组件
// 特点（* 为目标） ：
// 1、能够直接使用ag-grid的大部分特性
// 2、通过简单的设置完成基本的表格展示功能
// 3、*热拔插式表格组件
import { AgGridVue } from "ag-grid-vue";

//单元格组件
import ButtonCell from './cellComponents/ButtonCell';
import BooleanCell from './cellComponents/BooleanCell';
import ImageCell from './cellComponents/ImageCell';
import QrcodeCell from './cellComponents/QrcodeCell';
//过滤组件
import DictFilter from './filter/dictFilter.js';
//编辑组件
import DictCellEditor from './editComponents/dictCellEditor';
//状态栏组件
import toGridColumns from './column/columnTrans';
import flat from './column/flat';
import afterLoad from './afterLoad' //读取数据后的处理方法，包括异步翻译与小计
import { tools, http } from 'hq-tools';
import lodash from 'lodash';
import localeText from './options/localeText';//本地化翻译
import defaultColDef from './options/defaultColDef';

import FastQueryModal from './fastQuery/fastQueryModal';

import info from './info'
import columnTypes from './column/defaultColumnTypes';
import print from './print'
import exportExcel from './exportExcel'

import configDataCreator from './utils/configDataCreator'
export default {
	name: 'HongqiGrid',
	components: {
		AgGridVue,
		FastQueryModal,
		BooleanCell,
		//按钮
		ButtonCell,
		//图片
		ImageCell,
		//二维码
		QrcodeCell
	},
	props: {
		//表格名
		name: {
			type: String,
			default() {
				return 'table';
			}
		},
		//主题
		theme: {
			type: String,
			default() {
				return 'material';
			},
			validator(theme) {
				if (['balham', 'material', 'fresh', 'blue', 'dark', 'bootstrap'].indexOf(theme) > -1) {
					return true;
				};
			},
		},
		//字典
		dicts: {
			type: Object,
			default() {
				return {};
			}
		},
		//列定义
		columns: {
			type: Array,
			required: true,
			default() {
				return [];
			}
		},
		//数据
		data: {
			type: Array,
			default() {
				return [];
			}
		},
		//分页功能设置，包括【远程分页接口url】
		pagerOpts: {
			type: Object,
			default() {
				return {
					loadUrl: null
				};
			}
		},
		//表格设置
		gridOpts: {
			type: Object,
			default(value) {
				return {};
			}
		},
		//每页尺寸可选列表
		pageSizeOpts: {
			type: Array,
			default() {
				return [10, 50, 100, 500];
			}
		},
		//左下方工具条
		tools: {
			type: Array,
			validator(tools) {
				for (let tool of tools) {
					if (['exportCsv', 'exportExcel', 'print', 'exportExcel', 'refresh', 'fastquery', 'config'].indexOf(tool) < 0) {
						return false;
					}
				}
				return true;
			},
			default() {
				return ['exportCsv', 'exportExcel', 'refresh', 'fastquery', 'print', 'config'];
			}
		},
		//扩展组件，当需要使用自定义组件时接入
		frameworkComponents: {
			type: Object,
			default() {
				return null;
			}
		},
		height: {
			type: String,
			default() {
				return '600px';
			}
		},
		columnTrans: {
			type: Boolean,
			default: () => {
				return false
			}
		}
	},
	data() {
		return {
			//实际应用与表格的表格设置选项
			gridOptions: null,
			//表格的api，单独提出方便调用
			gridApi: null,
			//列的api，单独提出方便调用
			columnApi: null,
			//实际应用于表格的列定义
			columnDefs: null,
			//表格本地化文件
			localeText: localeText,
			//应用于表格的列定义
			formatedColumns: [],
			//实际应用与表格的数据，不管是远程获取的分页数据还是本地传入的数据
			rowData: [],
			//分页传输实体，与后端pagerModel对应
			pager: {
				nowPage: 1,
				pageSize: 10,
				pageCount: 0,
				recordCount: 0,
				errorMessage: null,
				exhibitDatas: [],
				externalObj: {},
				externalParameters: [],
				fastQueryParameters: []
			},
			//表格实际使用字典，传入字典与异步翻译的字典都在这里
			gridDicts: {},
			//混合后的表格设置选项，中间变量
			gridmixinedOpts: {},
			//前后文，用于表格内部组件调用等
			context: null,
			//高级查询弹出
			fastQueryShow: false,
			//设置弹出框弹出
			configShow: false,
			//高级查询输出
			advanceFastQueryParams: [],
			//导出弹窗弹出
			exportModal: false,
			//导出设置
			exportConfig: {
				state: "0",
				max: 5000
			},
			//读取状态
			loading: false,
			//设置表格列定义
			configData: []
		}
	},
	computed: {
		gridStyle() {
			return {
				'height': this.height ? `calc(${this.height} - 50px)` : null
			}
		},
		flatColumns() {
			return flat(this.formatedColumns)
		},
		exportURL() {
			if (this.pagerOpts.loadUrl) {
				let str = this.pagerOpts.loadUrl.match(/pager\w+|pager/)[0];
				return this.pagerOpts.loadUrl.replace(str, str + "Export");
			}
		},
		gridFrameworkComponents() {
			return this.frameworkComponents;
		}
	},
	watch: {
		//当字典变化时自动混入
		dicts(to) {
			this.gridApi.refreshCells({ force: true, columns: this.formatedColumns.filter(column => column.cellRendererParams && column.cellRendererParams.asyncTranslate).map(item => item.colId) });
		},
		//当数据发生变化时自动重载表格
		data(to) {
			this.load(to);
		},
		columns(to) {
			this.formatedColumns = toGridColumns(this.columns, this.gridmixinedOpts);
			this.configData = configDataCreator(this.formatedColumns);
		}
	},
	beforeMount() {
		//默认表格被指选项
		const gridOptsDefs = {
			defaultColDef,
			columnTypes,
			rowIndex: true,
			rowSelection: null,
			subTotal: false,
			suppressRowClickSelection: true,
			enableCellTextSelection: true,
			enableBrowserTooltips: true,
			onSelectionChanged: (params) => {
				this.$emit('selection', this.gridApi.getSelectedRows())
			}
		}

		//看起来及其愚蠢
		this.gridmixinedOpts = Object.assign({}, gridOptsDefs, this.gridOpts);
		//去掉一些ag-grid不使用的属性，避免控制台的警告
		this.gridOptions = Object.assign({}, this.gridmixinedOpts);
		//TODO
		delete this.gridOptions.subTotal;
		delete this.gridOptions.rowIndex;
		delete this.gridOptions.onBtnClickFunc;
		delete this.gridOptions.otherConfig;
		this.pager = Object.assign(this.pager, { pageSize: this.pageSizeOpts[0], exhibitDatas: this.data })

		this.formatedColumns = toGridColumns(this.columns, this.gridmixinedOpts);
		this.configData = configDataCreator(this.formatedColumns);
		//注册事件中使用的前后文
		this.context = {
			gridDicts: this.gridDicts,
			originColumns: this.columns,
			onBtnClickFunc: this.gridOpts.onBtnClickFunc,
			otherConfig: this.gridOpts.otherConfig,
			onBtnClick: (eventName, params) => {
				this.$emit('btnclick', {
					name: eventName,
					params: {
						rowIndex: params.rowIndex,
						row: params.data,
						column: params.colDef
					}
				});
			},
			selectedRow: new Map(),
			dicts: this.dicts
		};
	},
	beforeDestroy() {
		this.gridOptions = null;
		this.gridApi = null;
		this.columnApi = null;
		this.columnDefs = null;
		this.localeText = null;
		this.rowData = null;
		this.pager = null;
		this.gridDicts = null;
		this.gridmixinedOpts = null;
		this.context = null;
		this.fastQueryShow = null;
		this.advanceFastQueryParams = null;
	},
	methods: {
		//在表格准备完成后调用
		onGridReady(params) {
			// 获取gridApi
			this.gridApi = params.api;
			this.columnApi = params.columnApi;
			this.$emit('grid-ready', this);
			//console.log(this)
		},
		//高级查询
		onFastQuerySearch(advanceFastQueryParams) {
			this.advanceFastQueryParams = advanceFastQueryParams;
			this.load();
		},
		//读取数据
		load(data) {
			if (data) {
				this.rowData = lodash.cloneDeep(data);
				return this.dataHanddle();
			}
			if (!this.pagerOpts) {
				return this.$Message.error('表格不是分页类型！')
			}
			if (!this.pagerOpts.loadUrl) {
				return this.$Message.error('pagerOpts缺少属性：loadUrl')
			}
			this.pager = Object.assign(this.pager, this.pagerOpts, {
				fastQueryParameters: [].concat(this.pagerOpts.fastQueryParameters ? this.pagerOpts.fastQueryParameters : []).concat(this.advanceFastQueryParams)
			})
			this.loading = true;
			return new Promise((resolve, reject) => {
				this.$http.getByPager(this.pagerOpts.loadUrl, Object.assign({}, this.pager, { exhibitDatas: [] }))
					.then(pager => {
						this.pager = Object.assign(pager, {
							fastQueryParameters: this.pager.fastQueryParameters,
							externalParameters: this.pager.externalParameters
						});
						this.rowData = pager.exhibitDatas;
						this.dataHanddle();
						resolve({
							gridApi: this.gridApi,
							columnApi: this.columnApi
						});
						this.$emit('on-load-success', pager)
					})
					.catch(error => {
						console.error(error);
						reject(error)
					})
					.then(data => {
						this.loading = false;
					})
			})

		},
		dataHanddle() {
			let { subTotal } = afterLoad(this.rowData, this.flatColumns, this);
			this.context.subTotal = subTotal;

			if (this.gridmixinedOpts.subTotal && this.gridmixinedOpts.subTotal !== 'panel') {
				this.rowData.push(subTotal);
			}
			this.$nextTick(() => {
				this.gridApi.sizeColumnsToFit();
			})
			this.$emit('on-data-ready', this.rowData);
		},
		pageChange(nowPage) {
			this.pager.nowPage = nowPage;
			this.$emit('on-page-change', this.pager);
			this.load();
		},
		pageSizeChange(pageSize) {
			this.pager.pageSize = pageSize;
			this.$emit('on-page-size-change', this.pager);
			this.load();
		},
		exportCsv() {
			this.gridApi.exportDataAsCsv({
				columnGroups: true,
				fileName: this.name + '.csv',
				customHeader: this.name,
				customFooter: `共${this.pager.pageCount}页，${this.pager.recordCount}条；第${this.pager.nowPage}页`
			});
		},
		exportExcelModalShow() {
			this.exportConfig.state = "0";
			this.exportConfig.max = this.pager.recordCount;
			this.exportModal = true;
		},
		exportExcel() {
			if (!this.exportURL) {
				return '无导出链接，无法导出excel'
			}
			this.$Message.info("开始导出");
			exportExcel({
				exportFileName: this.name,
				exportURL: this.exportURL,
				exportColumns: this.columnApi.getAllGridColumns(),
				pager: this.pager,
				context: this.context,
				exportConfig: this.exportConfig,
				vm: this
			})
		},
		//打印
		print() {
			let columns = this.formatedColumns;
			let datas = this.gridApi.getModel().rowsToDisplay.map(item => item.data);
			print(datas, columns, this.flatColumns, this.context, this.name)
		},
		getSelections(withRowIndex = false) {
			if (withRowIndex) {
				return [...this.context.selectedRow];
			} else {
				return [...this.context.selectedRow].map(item => item[1]);
			}
		},
		showInfo() {
			this.$Modal.info({
				title: '注意事项',
				content: info,
				width: 600
			});
		},
		onConfigClick(selection, node) {
			this.hideColumn(node.column, !node.hide)
		},
		hideColumn(column, visible) {
			if (column && !column.groupId) {
				this.columnApi.setColumnVisible(column.colId, visible);
				if (column.children && column.children.length > 0) {
					for (let child of column.children) {
						this.columnApi.setColumnVisible(child.colId, visible);
					}
				}
			}
		}
	}
}
</script>

<style lang="scss" scoped>
@import "~ag-grid-community/dist/styles/ag-grid.css";
@import "~ag-grid-community/dist/styles/ag-theme-material.css";
// @import "~ag-grid-community/dist/styles/ag-theme-balham.css";
// @import "~ag-grid-community/dist/styles/ag-theme-fresh.css";
// @import "~ag-grid-community/dist/styles/ag-theme-blue.css";
// @import "~ag-grid-community/dist/styles/ag-theme-dark.css";
// @import "~ag-grid-community/dist/styles/ag-theme-bootstrap.css";
@import "./grid.scss";
</style>