var Editor: Editor = {
	elements: {
		container: document.querySelector('.edit'),
		appearence: {
			text: {
				content: document.querySelector('.ap_text_value'),
				size: document.querySelector('.ap_text_size'),
				color: document.querySelector('.ap_text_color'),
				offsetX: document.querySelector('.ap_text_offsetx').querySelector('input[type="range"]'),
				offsetY: document.querySelector('.ap_text_offsety').querySelector('input[type="range"]')
			},
			background: {
				color: document.querySelector('.ap_background_color')
			},
			image: {
				size: document.querySelector('.ap_image_size').querySelector('input[type="range"]'),
				offsetX: document.querySelector('.ap_image_offsetx').querySelector('input[type="range"]'),
				offsetY: document.querySelector('.ap_image_offsety').querySelector('input[type="range"]'),
				rotation: document.querySelector('.ap_image_rotation').querySelector('input[type="range"]')
			}
		},
		imageui: {
			imagetypes: document.querySelector('.imagetype'),
			imageinfopanels: document.querySelector('.imagemenu').querySelector('.info'),
			imagepanels: document.querySelector('.row.image').querySelector('.panels'),
			advanced: document.querySelector('.row.image').querySelector('.advanced')
		},
		buttonui: {
			buttontypes: document.querySelector('.buttontype'),
			visual: document.querySelector('.vis'),
			actioninner: document.querySelector('.actioninner'),
			containerTitles: document.querySelector('.editcontainer').querySelectorAll('.containertitle')
		},
		checks: {
			toggle: {
				container: document.querySelector('.checks').querySelector('.check.toggle'),
				checkbox: document.querySelector('.checks').querySelector('.check.toggle').querySelector('input')
			},
			confirm: {
				container: document.querySelector('.checks').querySelector('.check.confirm'),
				checkbox: document.querySelector('.checks').querySelector('.check.confirm').querySelector('input')
			}
		}
	},

	currentX: null,
	currentY: null,
	currentKey: null,
	currentImageType: null,
	currentButtonType: null,
	isToggle: null,
	isConfirm: null,

	isOpen: false,

	registerChange() {
		if (Editor.currentKey != null) {
			var editorExport = Editor.export();
			KeyHandler.render(Editor.currentX, Editor.currentY, editorExport);

			socket.emit(
				'page',
				'setkey',
				PageHandler.currentPageID,
				Editor.currentX,
				Editor.currentY,
				editorExport,
				responseToken
			);
		}
	},

	listeners() {
		for (var inputCategory in Editor.elements.appearence) {
			for (var inputName in Editor.elements.appearence[inputCategory]) {
				var inputElement: HTMLInputElement = Editor.elements.appearence[inputCategory][inputName];

				inputElement.oninput = Editor.registerChange;

				if (inputElement.type == 'range')
					((range: HTMLInputElement, number: HTMLInputElement) => {
						range.addEventListener('input', () => {
							number.value = range.value;
						});
						number.addEventListener('input', () => {
							range.value = number.value;
							Editor.registerChange();
						});
					})(inputElement, inputElement.parentElement.querySelector('input[type="number"]'));
			}
		}

		Editor.elements.imageui.imagetypes.querySelectorAll('.selectoritem').forEach((item: HTMLDivElement) => {
			item.onclick = () => {
				var panelType: 'none' | 'icon' | 'upload' = <any>item.getAttribute('panel');

				Editor.selectImageTab(panelType);
			};
		});

		Editor.elements.buttonui.buttontypes.querySelectorAll('.buttonitem').forEach((item: HTMLDivElement) => {
			item.onclick = () => {
				var buttonType: 'empty' | 'custom' | 'pageup' | 'pagedown' = <any>item.getAttribute('type');

				Editor.selectButtonType(buttonType);
			};
		});

		Editor.elements.checks.toggle.container.onclick = () =>
			Editor.setActionOptions(!Editor.elements.checks.toggle.checkbox.checked, Editor.isConfirm);

		Editor.elements.checks.confirm.container.onclick = () =>
			Editor.setActionOptions(Editor.isToggle, !Editor.elements.checks.confirm.checkbox.checked);
	},

	export(): Page_Key {
		if (Editor.isOpen) {
			return {
				id: Editor.currentKey.id,
				actions: Editor.currentKey.actions,
				state: {
					type: Editor.currentButtonType,
					confirm: Editor.isConfirm,
					toggle: Editor.isToggle
				},
				appearence: {
					text: Editor.getElementCategoryValues('text'),
					background: Editor.getElementCategoryValues('background'),
					image: Editor.getElementCategoryValues('image')
				}
			};
		}
		return null;
	},

	open(x: string, y: string, key: Page_Key) {
		if (Editor.isOpen) Editor.close();
		Editor.currentKey = key;
		Editor.currentX = x;
		Editor.currentY = y;
		Editor.isOpen = true;

		document.querySelectorAll('.actionselector').forEach((selector: HTMLInputElement) => {
			selector.value = '';
		});

		// --------- TEXT ---------
		{
			var textElems = Editor.elements.appearence.text;
			var textData: Page_Key_Text = Editor.getAppearenceCategory('text', key);
			textElems.content.value = textData.value != undefined ? textData.value : '';
			textElems.size.value = textData.size != undefined ? String(textData.size) : '10';
			textElems.color.value = textData.color != undefined ? textData.color : '#000000';
			textElems.offsetX.value = textData.offsetX != undefined ? String(textData.offsetX) : '0';
			var offsetXNumber: HTMLInputElement = textElems.offsetX.parentElement.querySelector('input[type="number"]');
			offsetXNumber.value = textData.offsetX != undefined ? String(textData.offsetX) : '0';
			textElems.offsetY.value = textData.offsetY != undefined ? String(textData.offsetY) : '0';
			var offsetYNumber: HTMLInputElement = textElems.offsetY.parentElement.querySelector('input[type="number"]');
			offsetYNumber.value = textData.offsetY != undefined ? String(textData.offsetY) : '0';
		}

		// --------- BACKGROUND ---------
		{
			var backgroundElems = Editor.elements.appearence.background;
			var backgroundData: Page_Key_Background = Editor.getAppearenceCategory('background', key);
			backgroundElems.color.value = backgroundData.color != undefined ? backgroundData.color : '#000000';
		}

		// --------- IMAGE ---------
		{
			var imageElems = Editor.elements.appearence.image;
			var imageData: Page_Key_Image = Editor.getAppearenceCategory('image', key);
			imageElems.size.value = imageData.size != undefined ? String(imageData.size) : '100';
			var sizeNumber: HTMLInputElement = imageElems.size.parentElement.querySelector('input[type="number"]');
			sizeNumber.value = imageData.size != undefined ? String(imageData.size) : '100';
			imageElems.rotation.value = imageData.rotation != undefined ? String(imageData.rotation) : '0';
			var rotationNumber: HTMLInputElement = imageElems.rotation.parentElement.querySelector(
				'input[type="number"]'
			);
			rotationNumber.value = imageData.rotation != undefined ? String(imageData.rotation) : '0';
			imageElems.offsetX.value = imageData.offsetX != undefined ? String(imageData.offsetX) : '0';
			var offsetXNumber: HTMLInputElement = imageElems.offsetX.parentElement.querySelector(
				'input[type="number"]'
			);
			offsetXNumber.value = imageData.offsetX != undefined ? String(imageData.offsetX) : '0';
			imageElems.offsetY.value = imageData.offsetY != undefined ? String(imageData.offsetY) : '0';
			var offsetYNumber: HTMLInputElement = imageElems.offsetY.parentElement.querySelector(
				'input[type="number"]'
			);
			offsetYNumber.value = imageData.offsetY != undefined ? String(imageData.offsetY) : '0';
		}

		if (imageData.address != undefined) {
			Editor.selectImageTab('upload', true);
		} else if (imageData.iconid != undefined) {
			Editor.selectImageTab('icon', true);
			Icons.select(imageData.iconid);
		}

		Editor.selectButtonType(key.state.type, true);
		Editor.setActionOptions(key.state.toggle, key.state.confirm, true);

		var actions = key.actions != undefined ? key.actions : { up: {}, down: {} };
		ActionEditor.open(actions, x, y, key, PageHandler.currentPageID);

		Editor.elements.container.classList.remove('disabled');
	},

	close() {
		Editor.isOpen = false;
		Editor.currentKey = null;
		Editor.currentX = null;
		Editor.currentY = null;

		document.querySelectorAll('.actionselector').forEach((selector: HTMLInputElement) => {
			selector.value = '';
		});

		var text = Editor.elements.appearence.text;
		text.content.value = 'Button';
		text.size.value = '20';
		text.color.value = '#ffffff';

		var background = Editor.elements.appearence.background;
		background.color.value = '#000000';

		Editor.elements.container.classList.add('disabled');

		Editor.selectImageTab('none', true);

		ActionEditor.close();

		Icons.deselect();
	},

	selectImageTab(panelType: 'none' | 'icon' | 'upload', ignoreUpdate = false) {
		Editor.elements.imageui.imagetypes.querySelectorAll('.selectoritem').forEach((selectoritem: HTMLDivElement) => {
			if (panelType == selectoritem.getAttribute('panel')) selectoritem.classList.add('selected');
			else selectoritem.classList.remove('selected');
		});
		Editor.elements.imageui.imagepanels.querySelectorAll('.panel').forEach((panel: HTMLDivElement) => {
			if (panelType == panel.getAttribute('panel')) panel.classList.add('selected');
			else panel.classList.remove('selected');
		});
		Editor.elements.imageui.imageinfopanels.querySelectorAll('.infopanel').forEach((infopanel: HTMLDivElement) => {
			if (panelType == infopanel.getAttribute('panel')) infopanel.classList.add('selected');
			else infopanel.classList.remove('selected');
		});

		Editor.currentImageType = panelType != 'none' ? panelType : null;

		if (panelType == 'none') Editor.elements.imageui.advanced.style.display = 'none';
		else Editor.elements.imageui.advanced.style.display = 'flex';

		if (panelType == 'icon') Icons.loadOnScreen();
		if (ignoreUpdate == false) Editor.registerChange();
	},

	selectButtonType(buttonType: KeyTypes, ignoreUpdate = false) {
		if (buttonType == 'ghost') buttonType = 'custom';

		Editor.elements.buttonui.buttontypes.querySelectorAll('.buttonitem').forEach((selectoritem: HTMLDivElement) => {
			if (buttonType == selectoritem.getAttribute('type')) selectoritem.classList.add('selected');
			else selectoritem.classList.remove('selected');
		});

		Editor.currentButtonType = buttonType;

		switch (buttonType) {
			case 'empty':
			case 'pageup':
			case 'pagedown':
			case 'currentpage':
				Editor.elements.buttonui.visual.style.display = 'none';
				Editor.elements.buttonui.actioninner.style.display = 'none';

				Editor.elements.buttonui.containerTitles.forEach((title) => (title.style.display = 'none'));
				break;

			case 'custom':
				Editor.elements.buttonui.visual.style.display = 'block';
				Editor.elements.buttonui.actioninner.style.display = 'block';
				Editor.elements.buttonui.containerTitles.forEach((title) => (title.style.display = 'flex'));
				break;
		}

		if (ignoreUpdate == false) Editor.registerChange();
	},

	setActionOptions(toggle: boolean, confirm: boolean, ignoreUpdate = false) {
		if (toggle) {
			ActionEditor.elements.up.container.style.display = 'none';
			ActionEditor.elements.latch.container.style.display = 'block';
		} else {
			ActionEditor.elements.up.container.style.display = 'block';
			ActionEditor.elements.latch.container.style.display = 'none';
		}
		if (confirm) {
			ActionEditor.elements.down.container.style.display = 'none';
		} else {
			ActionEditor.elements.down.container.style.display = 'block';
		}

		Editor.isToggle = toggle;
		Editor.isConfirm = confirm;

		Editor.elements.checks.toggle.checkbox.checked = toggle;
		Editor.elements.checks.confirm.checkbox.checked = confirm;

		if (ignoreUpdate == false) Editor.registerChange();
	},

	getAppearenceCategory(category: Editor_Categories, key: Page_Key = Editor.currentKey) {
		switch (category) {
			case 'text':
				var textData: Page_Key_Text =
					key.appearence != undefined && key.appearence.text != undefined
						? key.appearence.text
						: { value: '', size: 10, color: '#000000', offsetX: 0, offsetY: 0 };
				return textData;
			case 'background':
				var backgroundData: Page_Key_Background =
					key.appearence != undefined && key.appearence.background != undefined
						? key.appearence.background
						: { color: '#000000' };
				return backgroundData;
			case 'image':
				var imageData: Page_Key_Image =
					key.appearence != undefined && key.appearence.image != undefined
						? key.appearence.image
						: { offsetX: 0, offsetY: 0, size: 100, rotation: 0 };
				return imageData;
		}
	},

	getElementCategoryValues(category: Editor_Categories) {
		switch (category) {
			case 'text':
				var textData: Page_Key_Text = {
					value: Editor.currentButtonType != 'empty' ? Editor.elements.appearence.text.content.value : '',
					color:
						Editor.currentButtonType != 'empty' ? Editor.elements.appearence.text.color.value : '#ffffff',
					size:
						Editor.currentButtonType != 'empty' ? parseInt(Editor.elements.appearence.text.size.value) : 20,
					offsetX:
						Editor.currentButtonType != 'empty'
							? parseFloat(Editor.elements.appearence.text.offsetX.value)
							: 0,
					offsetY:
						Editor.currentButtonType != 'empty'
							? parseFloat(Editor.elements.appearence.text.offsetY.value)
							: 0
				};
				return textData;
			case 'background':
				var backgroundData: Page_Key_Background = {
					color:
						Editor.currentButtonType != 'empty'
							? Editor.elements.appearence.background.color.value
							: '#000000'
				};
				return backgroundData;
			case 'image':
				var imageData: Page_Key_Image = {
					size:
						Editor.currentButtonType != 'empty'
							? parseFloat(Editor.elements.appearence.image.size.value)
							: 100,
					rotation:
						Editor.currentButtonType != 'empty'
							? parseFloat(Editor.elements.appearence.image.rotation.value)
							: 0,
					offsetX:
						Editor.currentButtonType != 'empty'
							? parseFloat(Editor.elements.appearence.image.offsetX.value)
							: 0,
					offsetY:
						Editor.currentButtonType != 'empty'
							? parseFloat(Editor.elements.appearence.image.offsetY.value)
							: 0
				};

				if (Editor.currentImageType != null && Editor.currentButtonType != 'empty') {
					switch (Editor.currentImageType) {
						case 'icon':
							imageData.iconid = Icons.currentSelected;
							imageData.iconstyle = 'white';
							break;
					}
				}

				return imageData;
		}
	}
};

Editor.listeners();

interface Editor {
	elements: {
		container: HTMLDivElement;
		appearence: {
			text: {
				content: HTMLInputElement;
				size: HTMLSelectElement;
				color: HTMLInputElement;
				offsetX: HTMLInputElement;
				offsetY: HTMLInputElement;
			};
			background: {
				color: HTMLInputElement;
			};
			image: {
				size: HTMLInputElement;
				offsetX: HTMLInputElement;
				offsetY: HTMLInputElement;
				rotation: HTMLInputElement;
			};
		};
		imageui: {
			imagetypes: HTMLDivElement;
			imageinfopanels: HTMLDivElement;
			imagepanels: HTMLDivElement;
			advanced: HTMLDivElement;
		};

		buttonui: {
			buttontypes: HTMLDivElement;
			visual: HTMLDivElement;
			actioninner: HTMLDivElement;
			containerTitles: NodeListOf<HTMLDivElement>;
		};

		checks: {
			toggle: {
				container: HTMLDivElement;
				checkbox: HTMLInputElement;
			};
			confirm: {
				container: HTMLDivElement;
				checkbox: HTMLInputElement;
			};
		};
	};

	isOpen: boolean;
	currentKey: Page_Key;
	currentX: string;
	currentY: string;
	currentImageType: 'icon' | 'upload';
	currentButtonType: KeyTypes;
	isToggle: boolean;
	isConfirm: boolean;

	listeners: () => void;
	export: () => Page_Key;
	open: (x: string, y: string, key: Page_Key) => void;
	close: () => void;
	registerChange: () => void;
	selectImageTab: (panelType: string, ignoreUpdate?: boolean) => void;
	selectButtonType: (buttonType: KeyTypes, ignoreUpdate?: boolean) => void;
	setActionOptions: (toggle: boolean, confirm: boolean, ignoreUpdate?: boolean) => void;

	getAppearenceCategory: (category: Editor_Categories, key?: Page_Key) => any;
	getElementCategoryValues: (category: Editor_Categories) => any;
}

type Editor_Categories = 'text' | 'background' | 'image';
