// form/nc/nc-define/nc-database-editor/nc-database-editor.js

let selectedRow = null
let externalSelectedRow = null
let lastAction = null

function loadCallback() {
	const grid = state.grid.local_field
	const extGrid = state.grid.external_field
	setData('local_data', 1)
	setData('external_data', 1)
	nc.grid.dataChanged(grid, grid.data)
	nc.grid.dataChanged(extGrid, extGrid.data)
	nc.grid.redrawRows(state, 'local_field')
	nc.grid.redrawRows(state, 'external_field')
	nc.grid.activateRows(state, 'local_data', 1)
	nc.grid.activateRows(state, 'external_data', 1)
	// selectedRow = null
	// externalSelectedRow = null
	if (lastAction !== 'data') {
		// loadGrid('data')
	}
}
onMounted(() => {
	loadCallback()
	// loadGrid('data')
})

function addExampleData(arr, data, exampleData, prefix) {
	if (!prefix) {
		prefix = ''
	} else if (prefix.length > 0) {
		const lastChar = prefix.substring(prefix.length - 1)
		if (lastChar !== '.') {
			prefix = prefix + '.'
		}
	}
	for (const fieldName in exampleData) {
		if (fieldName !== 'idx') {
			const value = exampleData[fieldName]
			let rec =
				nc.findRecFromArr(data, 'field_name', prefix + fieldName) ||
				nc.findRecFromArr(data, 'field_name', 'json_data.' + prefix + fieldName) ||
				nc.findRecFromArr(arr, 'field_name', prefix + fieldName) ||
				nc.findRecFromArr(arr, 'field_name', 'json_data.' + prefix + fieldName)
			if (rec && fieldName !== 'json_data') {
				rec.example_data = value
			} else {
				rec = nc.findRecFromArr(data, 'local_field', prefix + fieldName) || nc.findRecFromArr(data, 'local_field', 'json_data.' + prefix + fieldName)
				if (rec && fieldName !== 'json_data') {
					rec.example_data = value
				}
				const type = typeof value
				if (type === 'string') {
					type === 'text'
				} else if (type === 'number') {
					type === 'double'
				}
				const item = {
					field_name: prefix + fieldName,
					field_type: type,
					type: 'data field',
					state: '',
					example_data: value,
					info: 'created from example data'
				}
				if (type === 'object' && exampleData[0]) {
					addExampleData(arr, data, exampleData[0], prefix.substring(0, prefix.length - 1) + '[1]')
				} else {
					if (fieldName !== 'json_data') {
						// add json_data separately to the end or arrays after normal data fields, with another call to this method
						arr.push(item)
						if (type === 'object') {
							addExampleData(arr, data, value, prefix + fieldName)
						}
					}
				}
			}
		}
	}
}

function setExampleData(data, exampleData, prefix) {
	let arr = []
	addExampleData(arr, data, exampleData, prefix)
	arr = arr.sort(nc.dynamicSort(['field_name', '>']))
	arr.forEach(item => {
		data.push(item)
	})
}

/* function findTable(arr, tableName, option) {
	let rec = arr.find(item => item.table_name === tableName)
	if (!rec && option === 'start') {
		rec = arr.find(item => peg.parseBefore(item.table_name, '-') === tableName)
	}
	return rec
}
let tablePathRec = findTable(rec.local_group_prf.group, rec.local_table)
*/

function setTab() {
	if (rec.tab === 'table') {
		hdr.nc_database_editor.label = hdr.nc_database_editor.local_field
		hdr.nc_database_editor.external_label = hdr.nc_database_editor.external_field
	} else if (rec.tab === 'database') {
		hdr.nc_database_editor.label = hdr.nc_database_editor.local_table
		hdr.nc_database_editor.external_label = hdr.nc_database_editor.external_table
	}
	/* if (rec.tab === 'connection') {
		hdr.nc_database_editor.label = hdr.nc_database_editor.local_database
		hdr.nc_database_editor.external_label = hdr.nc_database_editor.external_database */
}

function setSchema() {
	rec.schema = rec.connection
	const arrRec = nc.recordArrayRecord(arr.connection, 'value', rec.connection)
	if (arrRec?.schema) {
		rec.schema = arrRec.schema
	}
}

function loadGrid(action) {
	setSchema()
	lastAction = action
	const recParam = {
		action: action,
		tab: rec.tab,
		schema: rec.schema,
		connection: rec.connection,
		local_table: rec.local_table,
		external_default_field: rec.external_default_field,
		external_table: rec.external_table
	}
	const callParam = {
		name: 'form/nc/nc-define/nc-database-editor/grid.json',
		parameter: {
			rec: recParam
		},
		return: {
			grid: [
				{
					name: action === 'data' ? 'local_data' : 'local_field',
					tab: action === 'data' ? 'data' : rec.tab
				},
				{
					name: action === 'data' ? 'external_data' : 'external_field',
					tab: action === 'data' ? 'data' : rec.tab
				}
			]
		}
	}
	nc.callServer(state, 'query', callParam, loadCallback)
}

function changeTab() {
	setTab()
	setSchema()
	loadGrid('tab')
}

// eslint-disable-next-line no-unused-vars
function dropdown(action) {
	if (rec.tab === 'database') {
		changeTab()
		return
	}
	loadGrid(action)
}

// eslint-disable-next-line no-unused-vars
function gridContextMenu() {
	debugger
}

function setData(area, rowIndex) {
	let targetArea, fieldData, exampleData
	if (area === 'local_data') {
		targetArea = 'local_field'
		fieldData = state.grid.local_field.data
		exampleData = state.grid.local_data?.data || []
	} else if (area === 'external_data') {
		targetArea = 'external_field'
		fieldData = state.grid.external_field.data
		exampleData = state.grid.external_data?.data || []
	}
	const idx = nc.recordArrayIndex(fieldData, 'type', 'data field')
	if (idx > 0) {
		fieldData.length = idx - 1
	}
	exampleData = exampleData[rowIndex - 1]
	if (exampleData) {
		setExampleData(fieldData, exampleData) // setExampleData(fieldData, exampleData, 'no-json-prefix')
		if (exampleData.json_data) {
			setExampleData(fieldData, exampleData.json_data, 'json_data') // setExampleData(fieldData, exampleData, 'no-json-prefix')
		}
	}
	const dataRec = state.grid[area]?.data[rowIndex - 1]
	const grid = state.grid[targetArea]
	if (dataRec) {
		let item
		for (let index = 0; index < grid.data.length; index++) {
			item = grid.data[index]
			if (item.field_name && item.example_data == null) {
				const val = nc.recData(dataRec, item.field_name)
				item.example_data = val != null ? val : null
			}
			item.idx = index + 1
		}
	}
	nc.grid.dataChanged(grid, fieldData)
	// nc.grid.redrawRows(state, targetArea)
}

function otherArea(area) {
	if (area === 'local_field') {
		return 'external_field'
	}
	return 'local_field'
}

function selectMatchField(area, rowIndex) {
	if (area === 'external_field') {
		externalSelectedRow = rowIndex
	} else if (area === 'local_field') {
		selectedRow = rowIndex
	}
	const dataRec = state.grid[area].data[rowIndex - 1]
	const area2 = otherArea(area)
	if (dataRec && dataRec.local_field) {
		const localRec = nc.findRecFromArr(state.grid[area2].data, 'field_name', dataRec.local_field)
		if (localRec) {
			nc.grid.activateRows(state, area2, localRec.idx)
			if (area === 'external_field') {
				selectedRow = localRec.idx
			} else if (area === 'local_field') {
				externalSelectedRow = localRec.idx
			}
		}
	}
	if (dataRec && dataRec.local_table) {
		const localRec = nc.findRecFromArr(state.grid[area2].data, 'table_name', dataRec.local_table)
		if (localRec) {
			nc.grid.activateRows(state, area2, localRec.idx)
			if (area === 'external_field') {
				selectedRow = localRec.idx
			} else if (area === 'local_field') {
				externalSelectedRow = localRec.idx
			}
		}
	}
	return dataRec
}

// eslint-disable-next-line no-unused-vars
function matchField(fieldNumber) {
	debugger
	if (selectedRow == null || externalSelectedRow == null) return
	const externalRec = state.grid.external_field.data[externalSelectedRow - 1]
	const localRec = state.grid.local_field.data[selectedRow - 1]
	if (rec.tab === 'table') {
		if (externalRec.local_field === localRec.field_name) {
			// todo: set button to name unmatch and change icon on row click
			externalRec.local_field = ''
			localRec.local_field = ''
		} else {
			externalRec.local_field = localRec.field_name
			localRec.local_field = externalRec.field_name
		}
	} else if (rec.tab === 'database') {
		externalRec.local_table = localRec.table_name
		localRec.local_table = externalRec.table_name
		let idx
		if (externalRec.record_type == null) {
			idx = 0
		} else {
			idx = localRec.record_type.indexOf(externalRec.record_type)
			if (idx >= 0) {
				if (idx < localRec.record_type.length - 1) {
					idx++
				} else {
					idx = 0
				}
			} else {
				idx = 0
			}
		}
		externalRec.record_type = localRec.record_type[idx]
	}
	externalRec.state = 'match'
	localRec.state = 'match'
	let toIndex
	if (externalRec.type === 'data field') {
		const extFieldArr = rec.external_table_prf.field
		extFieldArr.push(externalRec)
		toIndex = extFieldArr.length
		externalRec.field_name = peg.parseAfter(externalRec.field_name, 'json_data.')
		externalRec.type = 'field'
		externalRec.idx = toIndex
		const extGrid = state.grid.external_field
		const arr = extGrid.data
		arr.splice(externalSelectedRow, 1) // remove data field -row
		arr.splice(toIndex - 1, 0, externalRec) // add field -row
		for (let index = 0; index < arr.length; index++) {
			const item = arr[index]
			item.idx = index + 1
		}
		nc.grid.dataChanged(extGrid, arr)
		nc.grid.activateRows(state, 'external_field', toIndex)
	}
	nc.grid.redrawRows(state, 'local_field')
	nc.grid.redrawRows(state, 'external_field')
}

function gridRowClicked(area, rowIndex, event, selected) {
	if (selected) {
		if (area === 'local_data' || area === 'external_data') {
			setData(area, rowIndex)
			nc.grid.redrawRows(state, 'local_field')
			nc.grid.redrawRows(state, 'external_field')
		} else if (area === 'local_field' || area === 'external_field') {
			const item = selectMatchField(area, rowIndex)
			if (rec.tab == 'database') {
				if (item) {
					if (item.local_table && item.table_name) {
						// match table
						rec.local_table = item.table_name
						rec.external_table = item.table_name // item.local_table
					} else if (area === 'local_field') {
						rec.local_table = item.table_name
						rec.external_table = ''
					} else if (area === 'external_field') {
						rec.local_table = ''
						rec.external_table = item.table_name
					}
				}
				loadGrid('data')
			}
		}
	}
}

// eslint-disable-next-line no-unused-vars
function gridRowDoubleClicked(area, rowIndex, event) {
	gridRowClicked(area, rowIndex, event, 'selected')
}

function setNewChangeRecord(gridData, dataRec, rowIndex) {
	// TODO: unique find by field type unique or primary key, not field_name
	// TODO: check allowed values from field preference
	if (dataRec.per && dataRec.field_name != null) {
		let idx = nc.recordArrayIndexLowerCase(gridData, 'field_name', dataRec.field_name)
		if (idx === rowIndex) {
			idx = nc.recordArrayIndexLowerCase(gridData, 'field_name', dataRec.field_name, idx + 1)
		}
		if (idx >= 0 || dataRec.field_name === '') {
			if (dataRec.changeRecord) {
				dataRec.changeRecord.duplicate = idx + 1
			} else {
				dataRec.changeRecord = { duplicate: idx + 1 }
			}
		} else if (dataRec.changeRecord && dataRec.changeRecord.duplicate != null) {
			delete dataRec.changeRecord.duplicate
		}
	}
}

function setChangeRecord(data, colId, oldValue, newValue) {
	if (data.changeRecord && data.changeRecord[colId] === newValue) {
		delete data.changeRecord[colId]
		if (nc.isEmptyObject(data.changeRecord)) {
			delete data.changeRecord
		}
	} else if (oldValue !== newValue) {
		if (data.changeRecord == null) {
			data.changeRecord = { [colId]: oldValue }
		} else if (data.changeRecord[colId] == null && oldValue !== newValue) {
			data.changeRecord[colId] = oldValue
		}
	}
}

function clearChangeRecord(data) {
	data.forEach(item => {
		delete item.changeRecord
		if (item.default_value === '') {
			delete item.default_value
		}
	})
}

// eslint-disable-next-line no-unused-vars
function gridCellValueChanged(area, node, data, newValue, oldValue, colId, rowIndex) {
	const gridData = state.grid[area].data
	setNewChangeRecord(gridData, data, rowIndex) // need to set value before cleaned
	if (typeof newValue === 'string') {
		const cleaned = peg.cleanBeforeAfterDoubleSpace(newValue)
		if (cleaned !== newValue) {
			newValue = cleaned
			nc.recDataSet(data, colId, newValue)
			setNewChangeRecord(gridData, data, rowIndex)
		}
	}
	setChangeRecord(data, colId, oldValue, newValue)
	nc.grid.refreshCells(state, area, node)
}

function cleanSaveRec(item) {
	delete item.changeRecord
	delete item.idx
	delete item.kind
	delete item.state
	delete item.example_data
}

// eslint-disable-next-line no-unused-vars
function save() {
	const param = {
		tab: rec.tab,
		schema: rec.schema,
		connection: rec.connection,
		update_external_database: rec.update_external_database,
		local_table: rec.local_table,
		external_default_field: rec.external_default_field,
		external_table: rec.external_table
	}
	if (rec.tab === 'table') {
		// debugger
		// param.field = nc.clone(state.grid.local_field.data).map(item => {
		param.field = nc.clone(rec.local_table_prf.field).map(item => {
			cleanSaveRec(item)
			delete item.local_field // no local_field in local table
			return item
		})
		if (rec.local_table_prf.extra_field) {
			param.extra_field = nc.clone(rec.local_table_prf.extra_field).map(item => {
				cleanSaveRec(item)
				delete item.local_field
				return item
			})
		}
		if (state.grid.external_field.data) {
			param.external_field = nc.clone(state.grid.external_field.data).map(item => {
				cleanSaveRec(item)
				return item
			})
		}
	} else if (rec.tab === 'database') {
		const externalTable = []
		let rec
		for (const item of state.grid.external_field.data) {
			if (item.local_table && item.table_name) {
				rec = {}
				rec.local_table = item.local_table
				rec.table_name = item.table_name
				rec.table_prefix = item.table_prefix
				rec.record_type = item.record_type || ''
				externalTable.push(rec)
			}
		}
		// param.table_arr = localTable
		param.external_group_prf = rec.external_group_prf
		param.external_table_arr = externalTable
	}
	nc.callServer(
		state,
		'save',
		{
			run: [{ function: 'nc-database-editor.saveTablePreference', parameter: [{ rec: param }] }]
		},
		() => {
			// console.log(`🚀 ~ file: nc-database-editor.js:474 ~ save ~ ret`, ret)
			clearChangeRecord(state.grid.local_field.data)
			clearChangeRecord(state.grid.external_field.data)
			nc.grid.redrawRows(state, 'local_field')
			nc.grid.redrawRows(state, 'external_field')
		}
	)
}

setSchema()
