/**
 * Created by rockyl on 2019-10-29.
 *
 * 行为编辑
 */

import Vue from "vue";
import i18n from "../../i18n";
import generateUUID from "uuid/v4";
import {clonePureObj, findMetaDepById, searchViewNode, updateProcesses} from "../../utils";

export const behaviorStore = {
	state: {
		projectData: {},
		processes: null,
		originProcesses: null,
		currentBehavior: null,
		processContext: [],
		currentProcess: null,
		lastProcess: null,

		processStack: [],
		editable: false,
		drawState: {
			drawing: false,
			targetUUID: '',
			lineID: 0,
			boardOffset: {x: 0, y: 0},
			boardScale: 1,
		},
		dirty: false,
	},
	mutations: {
		makeBehaviorDirty(state) {
			state.dirty = true;
		},
		clearBehavior(state) {
			state.dirty = false;
		},
		behavior_startEdit(state, {originData, behavior}) {
			state.projectData = originData;
			state.originProcesses = originData.processes;
			state.processes = clonePureObj(originData.processes);
			state.currentBehavior = clonePureObj(behavior);

			this.commit('clearBehavior');
			this.commit('updateCustomProcesses', state.processes);
		},
		behavior_save(state) {
			state.originProcesses.splice(0);
			state.originProcesses.push(...state.processes);
		},
		addProcessMeta(state, meta) {
			state.processes.push(meta);
			this.commit('makeBehaviorDirty');
			return process;
		},
		updateProcesses(state, {targetMetaID, replaceMetaID}) {
			updateProcesses(state.processes, targetMetaID, replaceMetaID);
		},
		deleteProcessMeta(state, {meta, process}) {
			let container;
			if (meta.isInline) {
				container = process.meta.metas;
			} else {
				container = state.processes;
			}
			if (container) {
				deleteProcessMeta(meta.id, container);
			}
			this.commit('makeBehaviorDirty');
		},
		clearProcessStack(state) {
			state.processStack.splice(0);
			updatePropsEditable(state);
			state.currentProcess = null;
		},
		pushProcessStack(state, process) {
			state.processStack.push(process);
			updatePropsEditable(state);
			state.currentProcess = process;
		},
		popProcessStack(state, index) {
			state.lastProcess = state.processStack.splice(index)[0];
			updatePropsEditable(state);
			state.currentProcess = state.processStack[state.processStack.length - 1];
		},
		setScale(state, value) {
			let scale = state.drawState.boardScale;
			if (value === 0) {
				scale = 1;
			} else {
				scale += value;
			}
			state.drawState.boardScale = Math.max(Math.min(4, scale), 0.1);
		},
		switchProcessInlineType(state, {process, parentMeta}) {
			let newMeta = process.meta;

			const {isInline} = newMeta;

			let oldUUID = newMeta.id;
			let newUUID = generateUUID();
			if (isInline) {
				newMeta.id = newUUID;
				newMeta.isInline = false;
				let index = parentMeta.metas.indexOf(newMeta);
				parentMeta.metas.splice(index, 1);
				state.processes.push(newMeta);

				for (let key in parentMeta.sub) {
					let subProcess = parentMeta.sub[key];
					if (subProcess.meta === oldUUID) {
						subProcess.meta = newUUID;
					}
				}
			} else {
				newMeta = clonePureObj(newMeta);

				newMeta.id = newUUID;
				newMeta.isInline = true;
				if(!parentMeta.metas){
					Vue.set(parentMeta, 'metas', []);
				}
				parentMeta.metas.push(newMeta);
				process.metaID = newUUID;
			}

			for (let key in parentMeta.sub) {
				let subProcess = parentMeta.sub[key];
				console.log(subProcess.meta);
			}

			this.commit('makeBehaviorDirty');
		},

	},
	getters: {
		customProcessMap: state => {
			let map = {};
			for (let process of state.processes) {
				map[process.id] = process;
			}
			return map;
		},
		metaInUse: state => targetMetaID => {
			return findMetaDepById(state.processes, targetMetaID);
		},
		metaIDExists: state => id => {
			let result = false;
			for (let process of state.processes) {
				if (process.id === id) {
					result = true;
					break;
				}
			}
			return result;
		},
		behavior_getAssetByUUID: state => uuid => {
			return state.projectData.assets.find(item => item.uuid === uuid);
		},
		behavior_views: state => {
			return state.projectData.views;
		},
		behavior_searchViewNode: state => uuid => {
			if (uuid) {
				return searchViewNode(state.projectData.views, uuid);
			}
		},
		processesInEditor(state) {
			return state.processes;
		},
	},
	actions: {
		addCustomProcessMeta({commit, state}, {masterProcess, isInline, processId, name}) {
			let meta = {
				id: generateUUID(),
				script: '',
				props: {},
				isInline,
				from: 'custom',
			};
			switch (processId) {
				case 'custom':
					meta.name = name || i18n.t('Custom');
					meta.output = ['success', 'failed'];
					break;
				case 'divider':
					meta.name = name || i18n.t('Divider');
					meta.output = ['p0'];
					meta.isDivider = true;
					break;
			}

			addProcessMeta(commit, isInline, masterProcess, meta);
			return meta;
		},
		addProcessFromPrefab({commit, state}, {masterProcess, isInline, meta: pMeta}) {
			let meta = clonePureObj(pMeta);
			meta.id = generateUUID();
			meta.isInline = isInline;
			meta.from = 'custom';
			delete meta.type;

			addProcessMeta(commit, isInline, masterProcess, meta);
			return meta;
		},
	}
};

function updatePropsEditable(state) {
	state.editable = state.processStack.filter(item => item.meta.type === 'builtin') <= 0;
}

function addProcessMeta(commit, isInline, masterProcess, meta) {
	if (isInline) {
		if (!masterProcess.meta.metas) {
			Vue.set(masterProcess.meta, 'metas', []);
		}
		masterProcess.meta.metas.push(meta);
	} else {
		commit('addProcessMeta', meta);
	}
}

export function addBehavior({alias, from}, processes) {
	let metaUUID = generateUUID();
	let behavior = {
		uuid: generateUUID(),
		meta: metaUUID,
	};
	let subEntryUUID = generateUUID();
	let p = {
		id: metaUUID,
		name: alias,
		props: {},
		subEntry: subEntryUUID,
		sub: {
			[subEntryUUID]: {
				uuid: subEntryUUID,
				alias: i18n.t('Entry'),
				meta: 'entry',
				design: {
					x: 10,
					y: 10,
				}
			},
		},
	};
	if (from) {
		p.from = from;
	}
	processes.push(p);
	return behavior;
}

export function deleteProcessMeta(metaId, processes) {
	for (let i = 0, li = processes.length; i < li; i++) {
		const process = processes[i];

		if (process.id === metaId) {
			processes.splice(i, 1);
			break;
		}
	}
}
