const os = require('os');
export * from '../ag-grid/index.ts';

/**
 * 根据Object生成sql
 * @param data Object类型数据
 * @param opts.type sql类型：新增(add) 删除(del) 修改(modify)
 * @param opts.table sql表名
 * @param opts.key sql中的判断主键字段名：... WHERE key=value
 * @param opts.exclude 需要从data中排除的字段
 * @param opts.fun 回调函数
 * @returns 生成的sql字符串
 */
export function createSqlByObject(
	data: { [key: string]: any }[],
	opts: {
		type: 'add' | 'del' | 'modify';
		table: string;
		key?: string;
		exclude?: string[];
		fun?: (
			row: { [key: string]: any },
			index: number,
			opts_: {
				type: 'add' | 'del' | 'modify';
				p1: string[];
				p2: any[];
			}
		) => void | string;
	}
) {
	return data.reduce((pre: string, row: { [key: string]: any }, rowIndex) => {
		const part1: any[] = []; // field 数组
		const part2: any[] = []; // value 数组
		// 处理单行数据
		if (opts.type !== 'del') {
			Object.entries(row).map(([field, value]) => {
				value = value.toString().trim();
				if (!value) return;
				if (opts?.exclude?.includes(field)) {
					// 除特殊字符外 直接跳过
				} else {
					// 新增 or 自定义
					if (opts.type === 'add') {
						part1.push(field);
						part2.push(`'${value}'`);
					}
					// 修改
					if (opts.type === 'modify') {
						part1.push(`${field} = ${value}`);
					}
				}
			});
		}
		// 回调
		opts.fun?.apply(window, [row, rowIndex, { type: opts.type, p1: part1, p2: part2 }]);
		// 新增
		if (opts.type === 'add') {
			pre += `INSERT INTO ${opts.table} (${part1.join(',')}) values (${part2.join(',')});`;
		}
		// 修改
		if (opts.type === 'modify') {
			if (opts.key) {
				pre += `UPDATA ${opts.table} SET ${part1.join(',')} WHEREW ${opts.key} = '${row[opts.key]};'`;
			} else {
				throw Error('[modify]时，[opts.key]不能为空');
			}
		}
		// 删除
		if (opts.type === 'del') {
			if (opts.key) {
				pre += `DELETE FROM ${opts.table} WHEREW ${opts.key} = '${row[opts.key]}';`;
			} else {
				throw Error('[del]时，[opts.key]不能为空');
			}
		}
		return pre;
	}, '');
}

/**
 * 指定数组中某段范围的数据移动到指定位置之后
 * @param arr 需要处理的数组
 * @param index_from 指定范围开始位置
 * @param index_to 指定范围结束位置
 * @param index_end 指定移动到的目标位置
 * @returns 返回重排序后的结果数组
 */
export function arrayMoveRangeToEnd(arr: { [key: string]: any }[], index_from: number, index_to: number, index_end: number) {
	// 判断是往前插入 还是 往后插入
	let res: any[] = [];
	if (index_end < index_from) {
		// 往前插入 需从尾部删除目标区域数据个数
		// 拆分为5个部分
		const top = arr.slice(0, index_end);
		const target = arr.slice(index_end, index_end + 1);
		const mid = arr.slice(index_end + 1, index_from);
		const range_data = arr.slice(index_from, index_to + 1);
		const btm = arr.slice(index_to + 1);
		// 重新组合5部分
		res = top.concat(target).concat(range_data).concat(mid).concat(btm);
	} else {
		// 往后插入
		// 拆分为5个部分
		const top = arr.slice(0, index_from);
		const range_data = arr.slice(index_from, index_to + 1);
		const mid = arr.slice(index_to + 1, index_end);
		const target = arr.slice(index_end, index_end + 1);
		const btm = arr.slice(index_end + 1);
		// 重新组合5部分
		res = top.concat(mid).concat(target).concat(range_data).concat(btm);
	}
	return res;
}

/**
 * 指定对象数组中某个成员对象的key-value，将对应成员移动到另一个成员value值的前面
 * @param arr 需要处理的数组
 * @param key 指定对象key
 * @param val_from 移动的key对应的value
 * @param val_to 移动的key对应的value
 * @returns 返回重排序后的结果数组
 */
export function arrayObjMoveToForward(arr: { [key: string]: any }[], key: string, val_from: string, val_to: string) {
	const i = arr.reduce(
		(pre: { index_from: number; index_to: number }, row, i) => {
			if (row[key] === val_from) {
				pre.index_from = i;
			}
			if (row[key] === val_to) {
				pre.index_to = i;
			}
			return pre;
		},
		{
			index_from: -1,
			index_to: -1,
		}
	);
	// plan_no_from plan_no_to 将数据分为3段
	let part1: any[] = [];
	let part2: any[] = [];
	let part3: any[] = [];
	let resGridData: { [key: string]: any }[] = [];
	if (i.index_from < i.index_to) {
		// 从上往下移
		part1 = arr.slice(0, i.index_from);
		part2 = arr.slice(i.index_from, i.index_to);
		part3 = arr.slice(i.index_to);
		part3.unshift(part2[0]);
		part2.splice(0, 1);
		resGridData = part1.concat(part2).concat(part3);
	}
	if (i.index_from > i.index_to) {
		// 从下往上移
		part1 = arr.slice(0, i.index_to);
		part2 = arr.slice(i.index_to, i.index_from);
		part3 = arr.slice(i.index_from);
		part1.push(part3[0]);
		part3.splice(0, 1);
		resGridData = part1.concat(part2).concat(part3);
	}
	return resGridData;
}

/**
 * 防抖函数
 * @param func 需要防抖的函数
 * @param wait 延迟时间
 * @param immediate 是否立即执行一次
 */
export function debounce(func: Function, wait = 0, immediate: boolean = false) {
	let timeout: NodeJS.Timeout | null;
	return function executedFunction(...args: any[]) {
		const later = function () {
			timeout = null;
			if (!immediate) func.apply(window, args);
		};
		const callNow = immediate && !timeout;
		timeout && clearTimeout(timeout);
		timeout = setTimeout(later, wait);
		if (callNow) func.apply(window, args);
	};
}

/**
 * 获取当前网络IP和MAC，vue中需挂载在vite.config.ts中运行，可通过全局变量/消息通信发送到页面
 */
export function getNetworkMacAndIp() {
	let IP = '127.0.0.1';
	let MAC = '';
	const networkInterfaces = os.networkInterfaces();
	for (const iface of Object.values(networkInterfaces)) {
		for (const details of iface as any) {
			if (details.family === 'IPv4' && details.mac !== '00:00:00:00:00:00' && details.address !== '127.0.0.1') {
				MAC = details.mac;
				IP = details.address;
				return { MAC, IP };
			}
		}
	}
	return { MAC, IP };
}

/**
 * 复制文本到剪切板，已过滤了兼容性
 * @param 需要复制的文本
 */
export function copyTextToClipboard(str: string) {
	if (navigator.clipboard) {
		// 框架对非安全模式浏览器做了限制
		navigator.clipboard.writeText(str);
	} else {
		// 这里做兼容性处理
		const dom = document.createElement('input');
		dom.value = str;
		document.body.appendChild(dom);
		dom.select();
		document.execCommand('copy');
		document.body.removeChild(dom);
		dom.remove();
	}
}

/**
 * 锚点缩放
 * @param topDomClassName 顶部锚点元素className
 * @param bottomDomClassName 底部锚点元素className
 * @param aim_rate 正确的锚点缩放比例
 * @param move_val 偏移值
 * @returns 相对于aim_rate的缩放比例
 */
export function getZoomByDoms(topDomClassName: string, bottomDomClassName: string, aim_rate: number, move_val: number = 0) {
	// 获取锚点的最顶部元素（锚点顶部）
	const mid_top_el = document.getElementsByClassName(topDomClassName)[0];
	// 获取锚点的最底部元素（锚点底部）
	const mid_bottom_el = document.getElementsByClassName(bottomDomClassName)[0];
	// 都获取到了
	if (mid_top_el && mid_bottom_el) {
		// 取锚点元素的高（锚点高度）
		const mid_height = getElClientRects(mid_bottom_el)?.leftTopPoint[1]! - getElClientRects(mid_top_el)?.leftTopPoint[1]! + move_val;
		// 当前计算出的相对于锚点-整个屏幕高度的比例
		const now_rate = mid_height / document.documentElement.clientHeight;
		// console.log('理论比:', aim_rate, '当前比:', now_rate);
		// console.log('相差缩放比:', aim_rate / now_rate, '约算结果:', Number((aim_rate / now_rate).toFixed(3)));
		// 计算出实际比与理论比的相对比 即最终结果
		return Number((aim_rate / now_rate).toFixed(3));
	}
	// 默认不缩放 即 1
	return 1;
}

/**
 * 获取元素尺寸信息
 * @param el 需要获取尺寸信息的元素
 */
export function getElClientRects(el: Element | HTMLElement) {
	if (el) {
		const el1_client_rects = el.getClientRects()[0];
		return {
			// 储存原始数据
			_client_rects: el1_client_rects,
			// 计算数据
			leftTopPoint: [el1_client_rects.x, el1_client_rects.y],
			leftBottomPoint: [el1_client_rects.x, el1_client_rects.y - el1_client_rects.height],
			rightTopPoint: [el1_client_rects.x + el1_client_rects.width, el1_client_rects.y],
			rightBottomPoint: [el1_client_rects.x + el1_client_rects.width, el1_client_rects.y - el1_client_rects.height],
		};
	}
	return null;
}

/**
 * 获取系统缩放比例
 */
export function reSetSysZoom() {
	let ratio = 0;
	let screen = window.screen as any;
	let ua = navigator.userAgent.toLowerCase();
	if (window.devicePixelRatio !== undefined) {
		ratio = window.devicePixelRatio;
	} else if (~ua.indexOf('msie')) {
		if (screen.deviceXDPI && screen.logicalXDPI) {
			ratio = screen.deviceXDPI / screen.logicalXDPI;
		}
	} else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
		ratio = window.outerWidth / window.innerWidth;
	}
	if (ratio) {
		ratio = Math.round(ratio * 100);
	}
	return 100 / Number(ratio);
}

/**
 * 下载文件
 * @param url 需要下载的文件url
 * @param success 下载成功后的回调函数
 */
export function downByUrl(url: string, success?: () => void) {
	const a = document.createElement('a');
	a.href = url;
	a.click();
	a.remove();
	success && success();
}

/**
 * Object深度合并
 * @param obj1 对象1
 * @param obj2 对象2,可选;为空时,程序等同于深拷贝
 * @returns 合并后的对象
 */
export function deepMerge(obj1: { [key: string]: any }, obj2?: { [key: string]: any }) {
	if (obj2) {
		const result = deepClone(obj1);
		for (const key in obj2) {
			const value = obj2[key];
			const isNorObj = typeof obj2[key] === 'object' && obj2[key] !== null;
			const isArr = Array.isArray(value);
			const isData = value instanceof Date;
			if (value && isNorObj && !isArr && !isData) {
				result[key] = deepMerge(result[key] || {}, obj2[key]);
			} else {
				result[key] = value;
			}
		}
		return result;
	} else {
		return deepClone(obj1);
	}
}

/**
 * 深拷贝
 * @param obj 对象
 * @param hash 通常无需传值
 * @returns 深拷贝后的对象
 */
export function deepClone(obj: { [key: string]: any }, hash = new WeakMap()) {
	if (obj === null) return null;
	if (obj instanceof Date) return new Date(obj);
	if (obj instanceof RegExp) return new RegExp(obj);
	if (typeof obj !== 'object') return obj;
	if (hash.has(obj)) return hash.get(obj);
	const cloneObj: { [key: string]: any } = Array.isArray(obj) ? [] : {};
	hash.set(obj, cloneObj);
	for (const key in obj) {
		if (obj.hasOwnProperty(key)) {
			cloneObj[key] = deepClone(obj[key], hash);
		}
	}
	return cloneObj;
}

/**
 * 将Map类型转换为eBFR字符串参数
 * @param map
 * @param addTimeStampOnEnd
 * @returns
 */
export function mapToeBFRParams(map: Map<string, string>, addTimeStampOnEnd = true) {
	const res = Array.from(map).map(([field, value]) => {
		return `@${field}@$$${value};;`;
	});
	if (addTimeStampOnEnd) {
		return res.join('') + new Date().getTime();
	}
	return res.join('');
}
