import {
	observable,
	action,
	computed
} from 'mobx';
import {
	WeaForm,
	WeaTableNew,
} from 'comsMobx';
import {
	WeaLocaleProvider,
} from 'ecCom';
import {
	Modal,
	Button,
	message,
} from 'antd';
import {
	toJS
} from 'mobx';
import {
	fetch,
	getMenusCreationConfig,
	getTopButtons,
	getDropMenuDatas,
	getSearchButtons,
	callback,
	componentReset,
	string,
	executeFunction,
	page,
} from '../util/save-time-util.js';
import {
	SearchForm
} from '../public/sweet-form.js';
const getLabel = WeaLocaleProvider.getLabel;
const confirm = Modal.confirm;
const {
	TableStore
} = WeaTableNew;

class CommonStore {
	hasOrgTree = true; //页面是否包含组织树
	hasAdvancedSearch = true; //页面是否包含高级搜索
	hasTable = true; //页面是否包含列表
	hasRadioGroup = false; //页面是否包含单选组合
	hasTab = false; //页面是否包含标签页
	isOrgTreeInfluenceForm = false; //组织树是否影响表单的生成

	asyncFetch; //异步请求
	customizedStore; //各个页面的store
	permissAsyncName; //权限接口名称
	menusAsyncName; //功能按钮接口名称
	searchAsyncName; //高级搜索接口名称
	tableAsyncName; //列表接口名称
	delAsyncName; //删除接口名称
	formAsyncName; //表单接口名称
	secondFormAsyncName; //同步设置表单接口名称
	addAsyncName; //新建保存接口名称
	editAsyncName; //编辑保存接口名称
	saveSecondFormAsyncName; //同步设置保存接口名称
	tabAsyncName; //标签页接口名称
	radioGroupAsyncName; //单选组合接口名称
	editIdPropertyName; //编辑保存id名称
	delIdPropertyName; //删除id名称
	searchLinkageFieldName; //高级搜索表单需要联动的表单域

	@action setPageConfig = (params) => {
		page.initConfig(params, this);
	}

	//************权限*************
	@observable pageAccessPermission = {
		hasRight: false,
		loading: true,
	}
	//获取页面权限
	@action getPermissionInfo = () => {
		fetch({
			asyncFetch: this.asyncFetch,
			name: this.permissAsyncName,
			logic: (cb) => {
				const {
					hasRight
				} = cb;

				if (hasRight) {
					this.pageAccessPermission.hasRight = true;
				}
				this.pageAccessPermission.loading = false;
			}
		});
	}

	@action resetAccessPermissionProps = () => {
		['hasRight', 'loading'].map((v, i) => {
			this.pageAccessPermission[v] = (i === 0) ? false : true;
		});
	}

	//*************头部**************
	topComponentStaticProps = {
		icon: <i className='icon-coms-hrm'/>,
		iconBgcolor: '#217346',
		showDropIcon: true
	};

	@observable top = {
		btnMenu: [],
	}

	//获取按钮、下拉菜单和右键菜单的复合数据
	@action getMenus = () => {
		const {
			menusParams,
		} = this.customizedStore;

		fetch({
			asyncFetch: this.asyncFetch,
			name: this.menusAsyncName,
			fetchParams: menusParams,
			logic: (cb) => {
				const {
					btnMenu,
					buttonSelect,
				} = cb;

				this.top.btnMenu = btnMenu;
			}
		});
	}

	//根据btnMenu，计算出topMenu和rightMenu
	@computed get menusCreationConfig() {
		const {
			btnMenu
		} = this.top;

		return getMenusCreationConfig(btnMenu);
	}

	//Top组件的按钮
	get topButtons() {
		const {
			topMenu
		} = this.menusCreationConfig;

		const {
			getMenusState
		} = this.customizedStore;

		return getTopButtons.call(this.customizedStore, {
			datas: topMenu,
			disabled: Array.isArray(getMenusState) ? getMenusState : getMenusState(),
		})
	}

	//获取右键菜单和top组件下拉菜单的数据
	get dropMenuDatas() {
		const {
			rightMenu
		} = this.menusCreationConfig;

		const {
			getMenusState
		} = this.customizedStore;

		return getDropMenuDatas.call(this.customizedStore, {
			datas: rightMenu,
			disabled: Array.isArray(getMenusState) ? getMenusState : getMenusState(),
		});

	}

	@action resetMenusConfig = () => {
		this.top.btnMenu = [];
	}

	//**************组织树******************
	@observable orgTree = {
		triggerRefresh: false,
		organizationId: '',
		organizationType: '0', //默认总部
	}

	//组织树点击事件的回调函数
	@action handleOrgTreeNodeClick = (params) => {
		const {
			id,
			type,
			name
		} = params;

		const {
			changeSpinning,
			resetTableEditableDatas,
			isNeedCallMenusAsyncFetch,
		} = this.customizedStore;

		//设置当前节点的类型
		this.orgTree.organizationType = type;
		//设置当前节点的ID
		this.orgTree.organizationId = id;
		//触发页面的加载状态
		changeSpinning && changeSpinning(true);
		//是否需要重新调用Menus接口
		isNeedCallMenusAsyncFetch && this.getMenus();
		//初始化高级搜索
		this.hasAdvancedSearch && this.initAdvanceSearch();
		//获取标签页数据、初始化标签页
		this.hasTab && this.getTabDatas();
		//重置单选组合
		this.hasRadioGroup && this.resetRadioGroup();
		//重置可编辑列表保存参数
		resetTableEditableDatas && resetTableEditableDatas();
		//刷新列表
		if (this.hasTable && !this.hasTab && !this.hasRadioGroup) {
			this.getSearchList();
		}
	}

	//手动刷新组织树
	@action triggerRefresh = () => {
		this.orgTree.triggerRefresh = !this.orgTree.triggerRefresh;
	}

	@action resetOrgTreeProps = () => {
		['organizationType', 'organizationId'].map((v, i) => {
			this.orgTree[v] = (i === 0) ? '0' : ''
		});
	}

	//***************高级搜索*****************
	@observable search = {
		isPanelShow: false,
		conditions: [],
		form: new WeaForm(),
	}

	//获取生成高级搜索表单的数据
	@action getSearchCondition = () => {
		fetch({
			asyncFetch: this.asyncFetch,
			name: this.searchAsyncName,
			logic: (cb) => {
				const {
					condition
				} = cb;

				this.search.conditions = condition;
				this.search.form.initFormFields(condition);
			}
		});
	}

	//获取高级搜索基本值
	@computed get searchBaseValue() {
		const {
			form
		} = this.search;

		return form.isFormInit ? form.getFormParams()[this.searchLinkageFieldName] : '';
	}

	//获取高级搜索表单
	get searchsAd() {
		const {
			form
		} = this.search;

		return <div
			onKeyDown={ (e) =>{
	            if (e.keyCode == 13 && e.target.tagName === "INPUT") {
	               ['changeSearchPanelStatus', 'getSearchList'].map((f, i) => this[f](i === 0 && false))
	            }
	        } }
		>{<SearchForm ecId={`${this && this.props && this.props.ecId || ''}_SearchForm@x285uz`} {...this.search} isFormInit={form.isFormInit}/>}</div>
	}

	//获取高级搜索按钮组
	get buttonsAd() {
		const {
			form
		} = this.search;

		const buttons = getSearchButtons({
			form,
			search: () => ['changeSearchPanelStatus', 'getSearchList'].map((f, i) => this[f](i === 0 && false)),
			cancel: () => this.changeSearchPanelStatus(false),
		});

		return buttons;
	}

	//获取高级搜索下拉面板的高度
	@computed get advanceHeight() {
		const {
			conditions
		} = this.search;

		const length = conditions.length > 0 ? conditions[0].items.length : 0;

		return Math.ceil(length / 2) * 52 + 20;
	}

	//改变下拉面板的状态
	@action changeSearchPanelStatus = (bool) => {
		this.search.isPanelShow = bool;
	}

	//联动高级搜索表单中的字段
	@action changeAdvanceSearchField = (val) => {
		const {
			form
		} = this.search;

		form.isFormInit && form.updateFields({
			[this.searchLinkageFieldName]: {
				value: val
			}
		})
	}

	//初始化高级搜索
	@action initAdvanceSearch = () => {
		const {
			form,
			isPanelShow,
		} = this.search;

		if (isPanelShow) this.changeSearchPanelStatus(false);

		if (form.isFormInit) {
			form.reset(); //点击当前菜单
		} else {
			this.search.form = new WeaForm(); //切换菜单
		}
	}

	@action resetSearchProps = () => {
		['conditions', 'form', 'isPanelShow'].map((v, i) => {
			this.search[v] = (i === 0) ? [] : (i === 1) ? new WeaForm() : false;
		});
	}

	//***************页签*****************
	@observable tab = {
		activeKey: '0',
		datas: [],
		ids: [],
	}

	//切换标签页
	@action setTabActiveKey = (key) => {
		const {
			handleTabClick
		} = this.customizedStore;

		this.tab.activeKey = key;
		handleTabClick && handleTabClick();
	}

	@action getTabDatas = () => {
		if (!this.tabAsyncName) return

		const {
			organizationType,
			organizationId
		} = this.orgTree;

		const params = {};

		if (this.hasOrgTree) {
			Object.assign(params, {
				organizationType,
				organizationId
			});
		}

		fetch({
			asyncFetch: this.asyncFetch,
			name: this.tabAsyncName,
			fetchParams: params,
			logic: (cb) => {
				const datas = callback.getArrayDatas(cb)
				const ids = callback.getTabId(cb);

				this.tab.datas = datas;
				this.tab.ids = ids;

				this.setTabActiveKey(0);
			}
		});
	}

	@action resetTabProps = () => {
		['activeKey', 'datas', 'ids'].map((v, i) => {
			this.tab[v] = (i === 0) ? '0' : [];
		})
	}

	//***************单选组合（RadioGroup）*****************
	@observable radioGroup = {
		config: [],
		activeParams: '',
	}

	@action getRadioGroupConfig = () => {
		fetch({
			asyncFetch: this.asyncFetch,
			name: this.radioGroupAsyncName,
			logic: (cb) => {
				//RadioGroup组件初始化的时候，会触发一次onChange事件，因此会调用一次列表接口，所以这里不需要重复调用列表接口。
				const {
					conditions
				} = cb;

				const {
					addCustomizedConfig,
					changeSpinning
				} = this.customizedStore;

				addCustomizedConfig && addCustomizedConfig(conditions, cb);

				this.radioGroup.config = conditions[0].items;

				changeSpinning && changeSpinning(false);
			}
		});
	}

	@action exportActiveParams = (params) => {
		const {
			isRequiredElementComplete
		} = this.customizedStore;

		this.radioGroup.activeParams = params;

		if (isRequiredElementComplete && isRequiredElementComplete(params)) {
			this.getSearchList();
		}
	}

	@action resetRadioGroup = () => {
		const {
			handleBrowserChange
		} = this.customizedStore;

		handleBrowserChange && handleBrowserChange('', false);
		//这里重置单选组合（RadioGroup）会连续触发两次onChange事件，因此会调用两次列表接口。
		['radioGroup', 'browser'].map(type => {
			this[`${type}_ref`] && componentReset[`reset${string.capitalize(type)}`](this[`${type}_ref`]);
		});
	}

	@action resetRadioGroupProps = () => {
		['config', 'activeParams'].map((v, i) => {
			this.radioGroup[v] = (i === 0) ? [] : '';
		});
		['radioGroup', 'browser'].map(v => {
			this[`${v}_ref`] = null;
		});
	}

	//***************列表*****************
	@observable table = {
		id: '',
		tableStore: new TableStore(),
		canViewTable: true,
	}

	@computed get radioGroupParams() {
		const {
			radioGroupCustomizedComParams
		} = this.customizedStore;

		return {
			...this.radioGroup.activeParams,
			...(radioGroupCustomizedComParams ? radioGroupCustomizedComParams : {})
		}
	}

	//获取列表数据
	@action getSearchList = (current) => {
		const {
			organizationId,
			organizationType
		} = this.orgTree;

		const params = {};

		if (this.search.form.isFormInit) {
			Object.assign(params, this.search.form.getFormParams());
		}

		if (this.hasOrgTree) {
			Object.assign(params, {
				organizationId,
				organizationType,
			});
		}

		if (this.hasRadioGroup) {
			Object.assign(params, this.radioGroupParams);
		}

		if (this.hasTab) {
			const {
				ids,
				activeKey
			} = this.tab;

			Object.assign(params, getTabParam && getTabParam.call(this));
		}

		const _current = current ? current : 1;

		this.resetTable();

		fetch({
			asyncFetch: this.asyncFetch,
			name: this.tableAsyncName,
			fetchParams: params,
			logic: (cb) => {
				const {
					sessionkey,
					status,
				} = cb;

				if (status && status === '-1') {
					this.table.canViewTable = false;
					return;
				}
				this.table.canViewTable = true;

				this.table.tableStore.getDatas(sessionkey, _current);

				const {
					receiveTableAsyncCallback
				} = this.customizedStore;

				receiveTableAsyncCallback && receiveTableAsyncCallback(cb);

			}
		});
	}

	//删除列表数据
	delTableRows = (type) => {
		const {
			id,
			tableStore
		} = this.table;

		fetch({
			asyncFetch: this.asyncFetch,
			name: this.delAsyncName,
			fetchParams: {
				[this.delIdPropertyName]: (type === 1) ? tableStore.selectedRowKeys.toString() : id,
			},
			logic: (cb) => {
				const {
					sign
				} = cb;

				if (sign === '1') {
					message.success(cb.message);
					this.getSearchList();
				} else {
					message.warning(cb.message);
				}
			}
		});
	}

	@action setSelectedRowId = (id) => {
		this.table.id = id;
	}

	@action setSelectedRowIndex = (index) => {
		this.table.index = index;
	}

	@action resetTable = () => {
		this.table.tableStore = new TableStore();
	}

	//**************弹框****************
	//弹框组件的常量参数
	dialogStaticProps = {
		icon: 'icon-coms-hrm',
		iconBgcolor: '#217346',
		hasScroll: true,
	}

	@observable dialog = {
		title: '',
		visible: false,
		type: 0,
	}

	@action openDialog = (params) => {
		const {
			title,
			type,
		} = params;

		['title', 'type', 'visible'].map((v, i) => {
			this.dialog[v] = (i < 2) ? params[v] : true;
		});
		//调用表单接口
		this.getFormMaterial();
	}

	@action closeDialog = () => {
		const {
			closeDialog
		} = this.customizedStore;

		//设置弹框隐藏
		this.dialog.visible = false;
		//重置表单数据
		this.resetForm();
		//不同页面，关闭弹框时，除了重置表单之外，还有其他的重置项。
		closeDialog && closeDialog();
	}

	//**************表单****************
	@observable formElements = {
		conditions: [],
		form: new WeaForm(),
		loading: true,
		date: new Date(), //用来刷新form组件
	}

	//获取表单数据
	@action getFormMaterial = () => {
		const {
			id,
			index,
		} = this.table, {
			type,
		} = this.dialog, {
			organizationType,
			organizationId
		} = this.orgTree;

		const fetchParams = (type === 1) ? {
			[this.editIdPropertyName]: id
		} : {};

		if (this.hasOrgTree && this.isOrgTreeInfluenceForm) {
			Object.assign(fetchParams, {
				organizationType,
				organizationId,
			});
		}

		const {
			isMainForm,
			setAdditionalFormDatas
		} = this.customizedStore;

		if (!isMainForm) {
			return
		}

		fetch({
			asyncFetch: this.asyncFetch,
			name: isMainForm() ? this.formAsyncName : this.secondFormAsyncName,
			fetchParams: fetchParams,
			logic: (cb) => {
				const {
					condition,
				} = cb;

				['loading', 'conditions', 'form'].map((v, i) => {
					if (i < 2) {
						this.formElements[v] = (i === 0) ? false : condition
					} else {
						this.formElements[v].initFormFields(condition);
					}
				});

				setAdditionalFormDatas && setAdditionalFormDatas(cb);
			}
		});
	}

	//保存表单信息
	saveFormDatas = () => {
		const {
			form
		} = this.formElements, {
			id
		} = this.table, {
			type
		} = this.dialog, {
			organizationType
		} = this.orgTree;

		const {
			neglectHiddenField,
			furtherValidate,
			isRepeat,
			isFieldRepeat,
			getAdditionalParams,
		} = this.customizedStore;

		//不检验隐藏的表单元素
		neglectHiddenField && neglectHiddenField();

		form.validateForm().then(f => {
			if (f.isValid) {
				//除了校验表单之外，不同的页面还有其他的校验项。
				if (furtherValidate && !furtherValidate()) return;

				//校验字段是否重复
				if (isRepeat) {
					isFieldRepeat && isFieldRepeat();
					return
				}
				//保存的参数包含：表单生成的参数和其他参数
				const fetchParams = Object.assign(form.getFormParams(), getAdditionalParams && getAdditionalParams());

				if (this.hasOrgTree) {
					Object.assign(fetchParams, {
						organizationType,
					});
				}

				(type === 1) && Object.assign(fetchParams, {
					[this.editIdPropertyName]: id
				});

				this.canOperateForm(false);

				fetch({
					asyncFetch: this.asyncFetch,
					name: (type === 0) ? this.addAsyncName : this.editAsyncName,
					fetchParams,
					logic: (cb) => {
						const {
							sign
						} = cb;

						if (sign === '1') {
							message.success(cb.message);
							this.closeDialog();

							const {
								tableStore
							} = this.table;

							const current = tableStore.current;

							this.getSearchList(current);
						} else {
							this.canOperateForm(true);
							message.warning(cb.message);
						}
					}
				});
			} else {
				f.showErrors();
				this.forceUpdateForm();
			}
		});
	}

	@action canOperateForm = (bool) => {
		this.formElements.loading = !bool;
	}

	@action forceUpdateForm = () => {
		this.formElements.date = new Date();
	}

	//重置表单
	@action resetForm = () => {
		['loading', 'conditions', 'form'].map((v, i) => {
			this.formElements[v] = (i === 0) ? true : (i === 1) ? [] : new WeaForm();
		});
	}

	setRef = (ref, type) => {
		this[`${type}_ref`] = ref;
	}

	refreshPage = () => {
		const {
			refreshPage
		} = this.customizedStore;

		//强制刷新左侧树
		this.hasOrgTree && this.triggerRefresh();

		this.handleOrgTreeNodeClick({
			id: '',
			type: '0'
		});

		//不同页面会有个性化的重置项
		refreshPage && refreshPage();
	}

	//重置页面配置项
	resetPageConfig = () => {
		['hasOrgTree', 'hasAdvancedSearch', 'hasTable'].map(v => {
			this[v] = true;
		});
		['hasRadioGroup', 'hasTab', 'isOrgTreeInfluenceForm'].map(v => {
			this[v] = false;
		});
	}

	//页面最高层级的组件在要挂起的时候调用这个函数，重置store中的属性
	//这里，不需要重置对象formElements内的属性，因为上个页面在关闭弹框时，会执行这一操作
	//不需要重置对象dialog内的属性，因为在打开弹框的时候，会对dialog对象内的属性进行赋值操作
	//不需要重置对象table内的属性，首先属性id不作为判断条件，其次在每次执行tableStore.getDatas()函数时，tableStore都会被重新new一次
	resetStorePropertys = () => {
		const {
			form
		} = this.formElements;

		['resetAccessPermissionProps', 'resetMenusConfig', 'resetOrgTreeProps', 'resetSearchProps',
			'resetTabProps', 'resetRadioGroupProps', 'resetPageConfig', 'resetForm'
		].map(f => {
			this[f]();
		});
	}

}

const commonStore = new CommonStore();

export {
	commonStore
}