// 流程设计 - 流程设计bpmn编辑器、版本管理 弹框
<template>
	<a-modal
		v-model:visible="confirmModalVisibleValue"
		:closable="false"
		:maskClosable="false"
		@cancel="$emit('confirm-modal-close')"
		:width="'100%'"
		:footer="null"
		class="publish-editor-modal"
		:bodyStyle="{
			'min-height': 'calc(100vh - 0px) !important',
			padding: '15px',
		}"
	>
		<ProcessDesign
			:process-design-visible="confirmModalVisibleValue"
			:process-design-id="processDesignIdValue"
			:process-design-key="processDesignKeyValue"
			:process-design-config="processDesignConfig"
			:permissionButtonData="customPermissionBtnOptions"
			:microflowItemList="customMicroflowOptions"
			:flowConditionalList="customFlowConditionOptions"
			:taskTitleList="customTaskTitleOptions"
			:custom-tab-options="customTabOptions"
			:customFormTabOptions="customFormTabOptions"
			:formItemList="customFormFieldsOptions"
			:formEngineItemList="customEngineFormFieldsOptions"
			:connectorsItemList="customConnectorsOptions"
			:formEngineeUrl="formEngineUrl"
			@confirm-modal-close="onModalClose"
		/>
	</a-modal>
</template>
<script lang="ts">
import router from '@/router'
import { getI18n } from '@/utils/i18n'
import { defineComponent, ref, watch, onMounted } from 'vue' // reactive

import { getConfigApi } from '@/api/system-config'

import {
	validatenull,
	arrayToTree,
	deepClone,
	isKeyType,
} from '@/utils/tool/translateValue'
import { ProcessConstant } from '@/utils/constant'
import { ProcessDesign } from 'jcbpm-vue-hi'

export default defineComponent({
	name: 'ProcessDesignPublishEditorModal',
	components: {
		ProcessDesign,
	},
	props: {
		// 操作确认弹出层是否展示
		confirmModalVisible: {
			type: Boolean,
			required: false,
			default: false,
		},
		// 流程设计列表 返回的id
		processDesignId: {
			type: String,
			default: '',
			required: false,
		},
		// key
		processDesignKey: {
			type: String,
			default: '',
			required: false,
		},
	},
	emits: ['confirm-modal-close'], // 'confirm-modal-confirm'
	setup(props, context) {
		const processDesignIdValue = ref<string>(props.processDesignId)
		const processDesignKeyValue = ref<string>(props.processDesignKey)
		const confirmModalVisibleValue = ref<boolean>(false)
		const formEngineUrl = ref(window['FORM_ENGINE_URL'])

		// bpmn流程设计 弹窗关闭
		const onModalClose = () => {
			processDesignIdValue.value = ''
			processDesignKeyValue.value = ''
			confirmModalVisibleValue.value = false

			context.emit('confirm-modal-close')
		}

		watch(
			() => props.confirmModalVisible,
			newValue => {
				confirmModalVisibleValue.value = newValue
				processDesignIdValue.value = props.processDesignId
				processDesignKeyValue.value = props.processDesignKey
			},
			{ deep: true, immediate: true }
		)
		// /(https?):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/
		const urlRE = /[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/
		function isURL(url) {
			return urlRE.test(url)
		}
		function stringToCode(code) {
			const returnFunc = `return ${code}`
			return new Function(returnFunc)()
		}
		function replaceUrl(method, url, data2) {
			const paramsCopy = deepClone(data2) || {}
			const matchList = url.match(/\{[a-zA-Z]+_*[a-zA-Z]*\}/g) || [] // /\{[a-zA-Z]+[\_]?[a-zA-Z]?\}/g
			matchList.forEach(p10 => {
				const key = p10.replace('{', '').replace('}', '')
				if (key in paramsCopy) {
					url = url.replace(p10, paramsCopy[key] || '')
					delete paramsCopy[key]
				} else {
					url = url.replace(p10, '')
				}
			})
			if (method === 'GET') {
				let searchParams = new URLSearchParams()
				for (let p10 in paramsCopy) {
					const value2 = paramsCopy[p10]
					const paramStr =
						typeof value2 === 'string'
							? value2
							: JSON.stringify(value2)
					searchParams.append(p10, paramStr)
				}
				if (searchParams.toString().length > 0) {
					if (url.includes('?')) {
						url = `${url}&${searchParams}`
					} else {
						url = `${url}?${searchParams}`
					}
				}
			}
			return url
		}
		function handleRequestOptions(method, url, data2) {
			let newUrl = replaceUrl(method, url, deepClone(data2))
			let newData = data2
			if (method === 'GET') {
				newData = {}
			}
			return { newUrl, newData }
		}
		function request(options) {
			return new Promise((resolve, reject) => {
				const {
					method = 'GET',
					url,
					data: data2,
					headers = {},
					responseType,
				} = options
				const { newUrl, newData } = handleRequestOptions(
					method,
					url,
					deepClone(data2)
				)
				const xhr = new XMLHttpRequest()
				xhr.responseType = responseType || 'text'
				xhr.open(method, newUrl, true)
				Object.keys(headers).forEach(key => {
					xhr.setRequestHeader(key, headers[key])
				})
				xhr.onerror = reject
				xhr.onload = () => {
					resolve(
						xhr.response ? JSON.parse(xhr.response) : xhr.response
					)
				}
				xhr.send(JSON.stringify(newData != null ? newData : ''))
			})
		}

		function handleDynamicRequest(dynamicRequest) {
			const { url, headers, method } = dynamicRequest
			if (!method) {
				return false
			}
			let newUrl = url
			if (!isURL(newUrl)) {
				return false
			}
			const newHeaders = { ...headers }
			return {
				...dynamicRequest,
				headers: newHeaders,
				url: newUrl,
			}
		}

		const getAPIData = async (requestObj: string, params?: any) => {
			let _requestObj
			if (requestObj) {
				const fn2 = stringToCode(requestObj)
				if (typeof fn2 === 'function') {
					_requestObj = fn2()
				}
			}
			if (!_requestObj) return []

			if (_requestObj instanceof Array) {
				return _requestObj
			} else if (isKeyType(_requestObj, 'object')) {
				if ('url' in _requestObj) {
					const { data, ...oth } = _requestObj
					data
					if (!validatenull(params)) {
						_requestObj = Object.assign(oth, { data: params })
					}
					const dynamicRequest = handleDynamicRequest(_requestObj)

					const res = await request(dynamicRequest)
					return res
				}
				return _requestObj
			}
		}

		// tool工具
		const getData = (data: any, key: string) => {
			let _keyArr = key ? key.split('.') : []
			let _retData =
				_keyArr && _keyArr.length > 0 ? data[_keyArr[0]] : data
			while (_keyArr && _keyArr.length > 0) {
				_keyArr.shift()
				_retData = getData(_retData, _keyArr.join('.'))
			}
			return _retData
		}
		const filterOption = ref<string[]>([
			'superiors',
			'direct-superiors',
			'peers',
			'inferiors',
			'direct-inferiors',
		])

		const processDesignConfig = ref()
		const customPermissionBtnOptions = ref()
		const customMicroflowOptions = ref()
		const customFlowConditionOptions = ref()
		const customTaskTitleOptions = ref()
		const customFormTabOptions = ref()
		const customTabOptions = ref()
		const customFormFieldsOptions = ref()
		const customEngineFormFieldsOptions = ref()
		const customConnectorsOptions = ref()

		// 查询
		const getConfig = async () => {
			await getConfigApi().then(res => {
				if (!validatenull(res.data)) {
					const _res = deepClone(res.data)
					const _formState = JSON.parse(_res[0].textJson)
					// 配置项
					if (!validatenull(_formState.processDesignConfig)) {
						getAPIData(_formState.processDesignConfig).then(res => {
							processDesignConfig.value = res
						})
					}
					// 权限按钮
					if (!validatenull(_formState.permissionButtonData)) {
						getAPIData(_formState.permissionButtonData).then(
							res => {
								if (!validatenull(res)) {
									customPermissionBtnOptions.value = res
								}
							}
						)
					}
					// 服务组件
					if (!validatenull(_formState.microflowItemList)) {
						const getMicroflowOptions = async param => {
							let paramObj = {}
							if (!validatenull(param)) {
								paramObj = Object.assign({}, param)
							}
							const res = getAPIData(
								_formState.microflowItemList,
								paramObj
							)
							return res
						}
						customMicroflowOptions.value = getMicroflowOptions
					}
					// 流程线 - 表达式
					if (!validatenull(_formState.flowConditionalList)) {
						const getFlowConditionOptions = async param => {
							let paramObj = {}
							if (!validatenull(param)) {
								paramObj = Object.assign({}, { formId: param })
							}
							const res = getAPIData(
								_formState.flowConditionalList,
								paramObj
							)
							return res
						}
						customFlowConditionOptions.value =
							getFlowConditionOptions
					}
					// 待办标题
					if (!validatenull(_formState.taskTitleList)) {
						const getTaskTitleOptions = async param => {
							let paramObj = {}
							if (!validatenull(param)) {
								paramObj = Object.assign({}, { formId: param })
							}
							const res = getAPIData(
								_formState.taskTitleList,
								paramObj
							)
							return res
						}
						customTaskTitleOptions.value = getTaskTitleOptions
					}

					// 设置经办者
					if (!validatenull(_formState.customTabOptions)) {
						const transactorsTabOpt = stringToCode(
							_formState.customTabOptions
						)
						if (isKeyType(transactorsTabOpt, 'function')) {
							const __transactorsTabOpt = transactorsTabOpt()
							if (!validatenull(__transactorsTabOpt)) {
								customTabOptions.value =
									__transactorsTabOpt?.map(v => {
										const {
											left = {},
											right = {},
											...oth
										} = v
										let obj = Object.assign({}, { ...oth })

										if (!validatenull(left)) {
											const { data, ...oths } = left
											left.value = {
												...oths,
												data: async param => {
													let paramObj = {}
													if (!validatenull(param)) {
														paramObj =
															Object.assign(
																{},
																deepClone(param)
															)
													}
													const res =
														await getAPIData(
															data,
															paramObj
														)

													let _preurlL = ''
													let _preBindDataL = ''
													let _preConfigDataL = {}
													let _preBindPageL = ''
													let _preConfigPageL = {}
													const _preDataFnL =
														stringToCode(data)
													if (
														isKeyType(
															_preDataFnL,
															'function'
														)
													) {
														_preurlL =
															_preDataFnL().url
														_preBindDataL =
															_preDataFnL()
																.bindData || ''
														_preConfigDataL =
															_preDataFnL()
																.configData ||
															{}
														_preBindPageL =
															_preDataFnL()
																.bindPage || ''
														_preConfigPageL =
															_preDataFnL()
																.configPage ||
															{}
													}
													/**
													 * 特殊情况 - 4A的lj接口 要特殊处理
													 * left tree posts
													 * left tree depts
													 * left tree user
													 * '/rbac-api/job-positions', '/rbac-api/departments', '/rbac-api/applications'
													 */

													if (
														_preurlL &&
														(_preBindDataL ||
															!validatenull(
																_preConfigDataL
															) ||
															_preBindPageL ||
															!validatenull(
																_preConfigPageL
															))
													) {
														let resData = {}
														switch (v.type) {
															case 'posts':
																let _dataposts =
																	getData(
																		res,
																		_preBindDataL
																	)
																_dataposts =
																	_dataposts.filter(
																		f =>
																			!filterOption.value.includes(
																				f.id
																			)
																	)
																if (
																	_preConfigDataL[
																		'arrayToTree'
																	]
																) {
																	_dataposts =
																		_dataposts.map(
																			v => {
																				return {
																					...v,
																					...{
																						key: v[
																							_preConfigDataL[
																								'key'
																							]
																						],
																						title: v[
																							_preConfigDataL[
																								'title'
																							]
																						],
																					},
																				}
																			}
																		)
																	let _datapostsTemp =
																		arrayToTree(
																			_dataposts,
																			'',
																			'parentId'
																		)
																	_dataposts =
																		!validatenull(
																			_datapostsTemp
																		)
																			? _datapostsTemp
																			: _dataposts
																}
																resData = {
																	data: _dataposts,
																}
																break
															case 'depts':
																let _datadepts =
																	getData(
																		res,
																		_preBindDataL
																	)
																if (
																	_preConfigDataL[
																		'jsonReplace'
																	]
																) {
																	const regxK =
																		new RegExp(
																			'' +
																				_preConfigDataL[
																					'key'
																				],
																			'g'
																		)
																	const regxT =
																		new RegExp(
																			'' +
																				_preConfigDataL[
																					'title'
																				],
																			'g'
																		)
																	_datadepts =
																		JSON.parse(
																			JSON.stringify(
																				_datadepts
																			)
																				.replace(
																					regxK,
																					'key'
																				)
																				.replace(
																					regxT,
																					'title'
																				)
																		)
																}
																if (
																	_preConfigDataL[
																		'arrayToTree'
																	]
																) {
																	_datadepts =
																		_datadepts.map(
																			v => {
																				return {
																					...v,
																					...{
																						key: v[
																							_preConfigDataL[
																								'key'
																							]
																						],
																						title: v[
																							_preConfigDataL[
																								'title'
																							]
																						],
																						deptId: v[
																							_preConfigDataL[
																								'deptId'
																							]
																						],
																						deptName:
																							v[
																								_preConfigDataL[
																									'deptName'
																								]
																							],
																					},
																				}
																			}
																		)
																	let _datadeptsTemp =
																		arrayToTree(
																			_datadepts,
																			'',
																			'parentId'
																		)
																	_datadepts =
																		!validatenull(
																			_datadeptsTemp
																		)
																			? _datadeptsTemp
																			: _datadepts
																}
																resData = {
																	data: _datadepts,
																}
																break
															case 'role':
																let _datarole =
																	getData(
																		res,
																		_preBindDataL
																	)
																_datarole =
																	_datarole.map(
																		v => {
																			return {
																				...v,
																				...{
																					key: v[
																						_preConfigDataL[
																							'key'
																						]
																					],
																					title: v[
																						_preConfigDataL[
																							'title'
																						]
																					],
																				},
																			}
																		}
																	)
																if (
																	_preConfigDataL[
																		'arrayToTree'
																	]
																) {
																	let _dataroleTemp =
																		arrayToTree(
																			_datarole,
																			'',
																			'parentId'
																		)
																	_datarole =
																		!validatenull(
																			_dataroleTemp
																		)
																			? _dataroleTemp
																			: _datarole
																}
																resData = {
																	data: _datarole,
																}
																break
															case 'user':
																let _datauser =
																	getData(
																		res,
																		_preBindDataL
																	)
																if (
																	_preConfigDataL[
																		'jsonReplace'
																	]
																) {
																	const regxK =
																		new RegExp(
																			'' +
																				_preConfigDataL[
																					'key'
																				],
																			'g'
																		)
																	const regxT =
																		new RegExp(
																			'' +
																				_preConfigDataL[
																					'title'
																				],
																			'g'
																		)
																	_datauser =
																		JSON.parse(
																			JSON.stringify(
																				_datauser
																			)
																				.replace(
																					regxK,
																					'key'
																				)
																				.replace(
																					regxT,
																					'title'
																				)
																		)
																}
																if (
																	_preConfigDataL[
																		'arrayToTree'
																	]
																) {
																	_datauser =
																		_datauser.map(
																			v => {
																				return {
																					...v,
																					...{
																						key: v[
																							_preConfigDataL[
																								'key'
																							]
																						],
																						title: v[
																							_preConfigDataL[
																								'title'
																							]
																						],
																						deptId: v[
																							_preConfigDataL[
																								'deptId'
																							]
																						],
																						deptName:
																							v[
																								_preConfigDataL[
																									'deptName'
																								]
																							],
																					},
																				}
																			}
																		)
																	let __datauserTemp =
																		arrayToTree(
																			_datauser,
																			'',
																			'parentId'
																		)
																	_datauser =
																		!validatenull(
																			__datauserTemp
																		)
																			? __datauserTemp
																			: _datauser
																}
																resData = {
																	data: _datauser,
																}
																break
															default:
																break
														}
														return resData
													}
													return res
												},
											}
											obj = Object.assign(obj, {
												left: left.value,
											})
										}
										if (!validatenull(right)) {
											const { data, ...oths } = right
											right.value = {
												...oths,
												data: async param => {
													let paramObj = {}
													if (!validatenull(param)) {
														paramObj =
															Object.assign(
																{},
																deepClone(param)
															)
													}
													const res =
														await getAPIData(
															data,
															paramObj
														)

													let _preurlR = ''
													let _preBindPageR = ''
													let _preConfigPageR = {}
													let _preBindDataR = ''
													let _preConfigDataR = {}
													const _preDataFnR =
														stringToCode(data)
													if (
														isKeyType(
															_preDataFnR,
															'function'
														)
													) {
														_preurlR =
															_preDataFnR().url
														_preBindPageR =
															_preDataFnR()
																.bindPage || ''
														_preConfigPageR =
															_preDataFnR()
																.configPage ||
															{}
														_preBindDataR =
															_preDataFnR()
																.bindData || ''
														_preConfigDataR =
															_preDataFnR()
																.configData ||
															{}
													}

													/**
													 * 特殊情况 - 4A的lj接口 要特殊处理
													 * right page user
													 * right page relations
													 */
													if (
														_preurlR &&
														(_preBindPageR ||
															!validatenull(
																_preConfigPageR
															) ||
															_preBindDataR ||
															!validatenull(
																_preConfigDataR
															))
													) {
														let resRightData = {}
														switch (v.type) {
															case 'user':
																let _pageuserR =
																	getData(
																		res,
																		_preBindPageR
																	)
																let _datauserR =
																	getData(
																		res,
																		_preBindDataR
																	)
																_datauserR =
																	_datauserR.map(
																		v => {
																			return {
																				id: v[
																					_preConfigDataR[
																						'id'
																					]
																				],
																				name: v[
																					_preConfigDataR[
																						'name'
																					]
																				],
																				deptId: v[
																					_preConfigDataR[
																						'deptId'
																					]
																				],
																				deptName:
																					v[
																						_preConfigDataR[
																							'deptName'
																						]
																					],
																			}
																		}
																	)
																resRightData = {
																	data: _datauserR,
																	current:
																		_pageuserR[
																			_preConfigPageR[
																				'current'
																			]
																		],
																	size: _pageuserR[
																		_preConfigPageR[
																			'size'
																		]
																	],
																	total: _pageuserR[
																		_preConfigPageR[
																			'total'
																		]
																	],
																}
																break
															case 'relations':
																let _datarelationsR =
																	getData(
																		res,
																		_preBindDataR
																	)
																_datarelationsR =
																	_datarelationsR.filter(
																		f =>
																			filterOption.value.includes(
																				f.id
																			)
																	)

																let _pagerelationsR =
																	getData(
																		res,
																		_preBindPageR
																	)
																resRightData = {
																	data: _datarelationsR,
																	current:
																		_pagerelationsR[
																			_preConfigPageR[
																				'current'
																			]
																		],
																	size: _pagerelationsR[
																		_preConfigPageR[
																			'size'
																		]
																	],
																	total: _pagerelationsR[
																		_preConfigPageR[
																			'total'
																		]
																	],
																}
																break
															default:
																break
														}
														return resRightData
													}
													return res
												},
											}
											obj = Object.assign(obj, {
												right: right.value,
											})
										}

										return obj
									})
							}
						}
					}
					// 设置表单
					if (!validatenull(_formState.customFormTabOptions)) {
						const formTabOpt = stringToCode(
							_formState.customFormTabOptions
						)
						if (isKeyType(formTabOpt, 'function')) {
							const __formTabOpt = formTabOpt()
							if (!validatenull(__formTabOpt)) {
								customFormTabOptions.value = __formTabOpt?.map(
									v => {
										const { data, ...oth } = v
										return {
											...oth,
											data: async param => {
												let paramObj = {}
												if (!validatenull(param)) {
													paramObj = Object.assign(
														paramObj,
														param
													)
												}
												if (
													isKeyType(data, 'function')
												) {
													paramObj = Object.assign(
														paramObj,
														data().data
													)
												}
												const res = await getAPIData(
													v.data,
													paramObj
												)
												return res
											},
										}
									}
								)
							}
						}
					}
					// 资源配置 - 表单字段选择
					if (!validatenull(_formState.customFormFieldsOptions)) {
						const getFormFieldsOptions = async param => {
							let paramObj = {}
							if (!validatenull(param)) {
								paramObj = Object.assign({}, param)
							}
							const res = getAPIData(
								_formState.customFormFieldsOptions,
								paramObj
							)
							return res
						}
						customFormFieldsOptions.value = getFormFieldsOptions
					}
					// 资源配置 - 表单字段选择 - 表单引擎的资源
					if (
						!validatenull(_formState.customEngineFormFieldsOptions)
					) {
						const getEngineFormFieldsOptions = async param => {
							let paramObj = {}
							if (!validatenull(param)) {
								paramObj = Object.assign({}, param)
							}
							const res = getAPIData(
								_formState.customEngineFormFieldsOptions,
								paramObj
							)
							return res
						}
						customEngineFormFieldsOptions.value =
							getEngineFormFieldsOptions
					}
					// 连接器
					if (!validatenull(_formState.customConnectorsOptions)) {
						const connectorsOpt = stringToCode(
							_formState.customConnectorsOptions
						)

						const getConnectorsOptions = async param => {
							let customDataParams
							if (isKeyType(connectorsOpt, 'function')) {
								const __connectorsOpt = connectorsOpt()
								if (!validatenull(__connectorsOpt)) {
									const { data } = __connectorsOpt
									customDataParams = data
								}
							}
							let paramObj = {}
							if (!validatenull(param)) {
								paramObj = Object.assign(paramObj, param)
							}
							if (!validatenull(customDataParams)) {
								paramObj = Object.assign(
									paramObj,
									customDataParams
								)
							}

							const res = getAPIData(
								_formState.customConnectorsOptions,
								paramObj
							)
							return res
						}
						customConnectorsOptions.value = getConnectorsOptions
					}
				}
			})
		}

		onMounted(() => {
			getConfig()
		})

		return {
			processDesignConfig,
			customPermissionBtnOptions,
			customMicroflowOptions,
			customFlowConditionOptions,
			customTaskTitleOptions,
			customFormTabOptions,
			customTabOptions,
			customFormFieldsOptions,
			customEngineFormFieldsOptions,
			customConnectorsOptions,

			router,
			getI18n,
			ProcessConstant,
			confirmModalVisibleValue,
			processDesignIdValue,
			processDesignKeyValue,
			onModalClose,
			formEngineUrl,
		}
	},
})
</script>
