/**
 * Created by rockyl on 2019-09-19.
 */

import {Message, Loading} from "element-ui";
import i18n from '../i18n'
import generateUUID from "uuid/v4";
import moment from "moment";
import zlib from "zlib";

/**
 * 动态数据图标映射
 * @type {{"data-center": string, static: string, scope: string, arguments: string, env: string}}
 */
export const dynamicIconMapping = {
	'static': 'S',
	'arguments': 'A',
	'data-center': 'D',
	'scope': 'O',
	'env': 'E',
};

export const typeMapping = [
	'library',
	'process',
	'script',
	'custom',
];

export const pxHostMapping = {
	dev: "activity.m.duibadev.com.cn",
	test: "activity.m.duibatest.com.cn",
	prod: "https://activity.m.duiba.com.cn"
};

export const monacoEditorOptions = {
	tabSize: 2,
	insertSpaces: false,
	automaticLayout: true,
};

export const cmdPrefix = 'z-';
export const cmdOldPrefix = '//z-';

/**
 * 节点方案
 * @type {string}
 */
export const nodeScheme = 'node://';
export const assetScheme = 'asset://';

/**
 * 弹出错误消息
 * @param e
 */
export function messageError(e) {
	Message({
		dangerouslyUseHTMLString: true,
		message: `<p style="margin-bottom: 5px;"><strong>${i18n.t(e.message)}</strong></p><p>${e.name}</p>`,
		type: 'error'
	})
}

/**
 * 播放等待动画
 * @param promise
 * @param text
 * @param closeLoading
 * @return {*}
 */
export function playWaiting(promise, text, closeLoading = true) {
	const loading = Loading.service({
		lock: true,
		text: text || i18n.t('In processing'),
	});

	return promise.catch(e => {
		messageError(e);
		throw e;
	}).finally(() => {
		if (closeLoading) {
			loading.close();
		}
	})
}

export function guid() {
	return `xy-${generateUUID()}`;
}

/**
 * 遍历视图节点
 * @param nodes
 * @param callback
 * @param parent
 */
export function traverseViewNode(nodes, callback, parent) {
	if (!nodes) {
		return;
	}
	for (let node of nodes) {
		callback(node, parent);
		if (node.children && node.children.length > 0) {
			traverseViewNode(node.children, callback, node);
		}
	}
}

export function strEllipsis(str, maxLength = 0, rightOffset = 0) {
	let result = str;
	let strLen = str.length;//stringWidth(str);
	if (strLen > maxLength) {
		strLen += 1; //还有一个省略号占1个半角
		let leftPart = str.substr(0, maxLength - rightOffset);
		let rightPart = str.substr(strLen - rightOffset);
		result = leftPart + '…' + rightPart;
	}
	return result;
}

export function getInputDefaultValue(property) {
	return property ? property.hasOwnProperty('default') ? property.default + '' : 'unset' : 'unset';
}

export function updateProcesses(processes, targetMetaID, replaceMetaID) {
	for (let process of processes) {
		for (let key in process.sub) {
			let subProcess = process.sub[key];
			if (subProcess.meta === targetMetaID) {
				subProcess.meta = replaceMetaID;
			}
		}
		if (process.metas) {
			updateProcesses(process.metas, targetMetaID, replaceMetaID)
		}
	}
}

/**
 * 过程元依赖过程
 * @param processMetas
 * @param metaId
 * @return {Array}
 */
export function findMetaDepById(processMetas, metaId) {
	let result = [];
	findMetaDepOnce(processMetas,
		function findProcessFilterById(process) {
			return process.meta === metaId;
		}, result);
	return result;
}

function findMetaDepOnce(processMetas, filter, result, parentPath = []) {
	for (let meta of processMetas) {
		let path = parentPath.concat();
		path.push(meta);
		for (let key in meta.sub) {
			let subProcess = meta.sub[key];
			if (filter(subProcess)) {
				path.push(subProcess);
				result.push(path);
			}
		}
		if (meta.metas && meta.metas.length > 0) {
			findMetaDepOnce(meta.metas, filter, result, path);
		}
	}
}

export function findProcess(rootMetas, builtinMetas, filter) {
	let result = [];
	findOnce(rootMetas);
	return result;

	function findOnce(metas, parentPath) {
		/*if (parentPath) {
			//let pathStr = parentPath.map(item=>item.name || item.metaName).join('>');
			let pathStr = parentPath.map(item => item.name || item.process.uuid.substr(0, 8)).join('>');
			console.log('findProcess', pathStr);
		}*/
		for (let meta of metas) {
			let path = parentPath ? parentPath : [];
			if (!parentPath) {
				path.push(meta);
			}
			for (let key in meta.sub) {
				let subProcess = meta.sub[key];
				if (path.find(item => item.process && item.process.uuid === subProcess.uuid)) {
					break;
				}
				let subMeta = meta.metas ? meta.metas.find(item => item.id === subProcess.meta) : null;
				if (!subMeta) {
					subMeta = rootMetas.find(item => item.id === subProcess.meta);
				}
				if (!subMeta) {
					subMeta = builtinMetas[subProcess.meta]
				}
				if (subMeta) {
					let newPath = path.concat();
					newPath.push({
						process: subProcess,
						metaName: subMeta.name,
					});
					if (filter(subProcess, subMeta)) {
						result.push(newPath);
					}
					findOnce([subMeta], newPath);
				}
			}
		}
	}
}

/**
 * 克隆纯数据对象
 * @param obj
 * @return {any}
 */
export function clonePureObj(obj) {
	return JSON.parse(JSON.stringify(obj));
}

/**
 * 保存到本地
 * @param blob
 * @param fileName
 */
export function saveAs(blob, fileName) {
	if ('msSaveOrOpenBlob' in navigator) {
		navigator.msSaveOrOpenBlob(blob, fileName);
	} else {
		const url = URL.createObjectURL(blob);
		const link = document.createElement('a');

		link.style.display = 'none';
		link.href = url;
		link.setAttribute('download', fileName);
		document.body.appendChild(link);
		link.click();
		document.body.removeChild(link);

		setTimeout(() => {
			URL.revokeObjectURL(url);
		}, 500);
	}
}

/**
 * 读取文本文件
 * @param file
 * @return {Promise}
 */
export function readTextFile(file) {
	return new Promise((resolve, reject) => {
		const fileReader = new FileReader();
		fileReader.readAsText(file);

		fileReader.addEventListener('load', function (e) {
			resolve(this.result);
		}, false);

		fileReader.addEventListener('error', function (e) {
			reject(e);
		}, false);
	})
}

/**
 * 扫描文件实体
 * @param item
 * @return {Promise}
 */
function scanEntries(item) {
	return new Promise(resolve => {
		if (item.isDirectory) {
			let directoryReader = item.createReader();

			directoryReader.readEntries(function (es) {
				resolve(es);
			});
		} else {
			resolve();
		}
	})
}

/**
 * 扫描文件
 * @param item
 * @param container
 * @return {Promise<void>}
 */
export async function scanFiles(item, container) {
	const entries = await scanEntries(item);
	if (entries) {
		for (let entry of entries) {
			container.push(entry);
			await scanFiles(entry, container);
		}
	}
}

/**
 * 选择文件
 * @param callback
 * @param accept
 * @param multiple
 * @param acceptDirectory
 */
export function selectFile(callback, {accept, multiple, acceptDirectory} = {}) {
	let input = document.createElement('input');
	input.type = 'file';
	input.onchange = function (e) {
		callback(input.files);
	};
	if (acceptDirectory) {
		input.webkitdirectory = true;
	}
	if (accept) {
		input.accept = accept;
	}
	if (multiple) {
		input.multiple = true;
	}
	input.click();
}

/**
 * 打开预览页面
 * @param packResult
 */
export function openPreview(packResult) {
	setTimeout(() => {
		let url;
		if (location.host.startsWith('localhost')) {
			url = packResult.tplUrl;
		} else {
			url = '/preview?url=http:' + packResult.tplUrl;
		}
		window.open(url, 'blank');
	}, 500);
}

/**
 * url包装script元素
 * @param url
 * @return {string}
 */
export function newScriptEl(url) {
	return `<script src="${url}"></script>`
}

/**
 * 内容包装script元素
 * @param content
 * @return {string}
 */
export function newScriptContent(content) {
	return `<script>${content}</script>`
}

/**
 * 获取mock服务启用状态
 * @param projectID
 * @return {boolean}
 */
export function getMockServeEnabled(projectID) {
	let enabled = localStorage.getItem('mock-enabled-' + projectID);
	if (enabled) {
		enabled = JSON.parse(enabled);
	}
	return !!enabled;
}

/**
 * 搜索视图节点
 * @param nodes
 * @param uuid
 * @param path
 */
export function searchViewNode(nodes, uuid, path = '') {
	for (let node of nodes) {
		if (node.uuid === uuid) {
			return {
				node,
				path: path + '/' + node.name,
			};
		} else if (node.children && node.children.length > 0) {
			let t = searchViewNode(node.children, uuid, path + '/' + node.name);
			if (t) {
				return t;
			}
		}
	}
}

/**
 * 获取视图节点路径（目前没有parent，所以无法使用）
 * @param node
 * @param sep
 */
export function getViewNodePath(node, sep = '/') {
	let cNode = node;
	let segs = [];
	while (cNode) {
		segs.unshift(cNode.name);
		cNode = cNode.parent;
	}
	return segs.join(sep)
}

export function timeFormat(time, format = 'YYYY-MM-DD HH:mm:ss') {
	return moment(time).format(format)
}

export function deleteDesignConfig(processes) {
	for (let process of processes) {
		if (process.sub) {
			for (let key in process.sub) {
				let p = process.sub[key];
				delete p.design['input'];
				delete p.design['output'];
			}
		}
		if (process.metas) {
			deleteDesignConfig(process.metas);
		}
	}
}

export function deleteAssetsDepConfig(data) {
	for (let asset of data.assets) {
		delete asset['dep'];
	}
}

export function formatJson(source) {
	return source ? JSON.stringify(JSON.parse(source), null, '\t') : '';
}

let transCanvas = document.createElement('canvas');

export async function transPngToJpg(img, type = 'blob', option) {
	const quality = option ? option.quality : 70;
	const bgColor = option ? option.bgColor : '#FFFFFF';
	if (!img) {
		return;
	}

	let imgOrigin;
	if (typeof img === 'string') {
		imgOrigin = new Image();
		imgOrigin.crossOrigin = 'anonymous';
		imgOrigin.src = img;
		await new Promise((resolve, reject) => {
			imgOrigin.onload = resolve;
			imgOrigin.onerror = reject;
		})
	} else {
		imgOrigin = img;
	}

	const {width, height} = imgOrigin;
	transCanvas.width = width;
	transCanvas.height = height;
	let ctx = transCanvas.getContext('2d');
	ctx.fillStyle = bgColor;
	ctx.fillRect(0, 0, width, height);
	ctx.drawImage(imgOrigin, 0, 0);
	let dataUrl = transCanvas.toDataURL('image/jpeg', quality / 100);

	let result;
	switch (type) {
		case 'img':
			let imgR = new Image();
			imgR.src = dataUrl;
			result = imgR;
			break;
		case 'blob':
			result = dataURLtoBlob(dataUrl);
			break;
	}

	return result;
}

export function dataURLtoBlob(dataUrl) {
	var arr = dataUrl.split(','), mime = arr[0].match(/:(.*?);/)[1],
		bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
	while (n--) {
		u8arr[n] = bstr.charCodeAt(n);
	}
	return new Blob([u8arr], {type: mime});
}

export async function zipViewFile(file) {
	let dataString = await readTextFile(file);

	let buf = new Buffer(dataString);
	return await new Promise((resolve, reject) => {
		zlib.gzip(buf, function (err, res) {
			if (err) {
				reject(err);
			} else {
				console.log(res.length);
				resolve(res);
			}
		})
	})
}
