/**
 * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
 * Copyright 2025 by Keenthemes Inc
 */

import KTData from '../../helpers/data';
import KTEventHandler from '../../helpers/event-handler';
import KTComponent from '../component';
import { KTImageInputInterface, KTImageInputConfigInterface } from './types';

declare global {
	interface Window {
		KT_IMAGE_INPUT_INITIALIZED: boolean;
		KTImageInput: typeof KTImageInput;
	}
}

export class KTImageInput extends KTComponent implements KTImageInputInterface {
	protected override _name: string = 'image-input';
	protected override _defaultConfig: KTImageInputConfigInterface = {
		hiddenClass: 'hidden',
	};
	protected _inputElement: HTMLInputElement;
	protected _hiddenElement: HTMLInputElement;
	protected _removeElement: HTMLElement;
	protected _previewElement: HTMLElement;
	protected _previewUrl: string = '';
	protected _lastMode: string;
	protected _selectedFile: File | null = null;

	constructor(element: HTMLElement, config?: KTImageInputConfigInterface) {
		super();

		if (KTData.has(element as HTMLElement, this._name)) return;

		this._init(element);
		this._buildConfig(config);

		this._inputElement = this._element.querySelector('input[type="file"]')!;
		this._hiddenElement = this._element.querySelector('input[type="hidden"]')!;
		this._removeElement = this._element.querySelector(
			'[data-kt-image-input-remove]',
		)!;
		this._previewElement = this._element.querySelector(
			'[data-kt-image-input-preview]',
		)!;

		this._update();
		this._handlers();
	}

	protected _handlers(): void {
		KTEventHandler.on(
			this._element,
			'[data-kt-image-input-placeholder]',
			'click',
			(event: Event) => {
				event.preventDefault();

				this._inputElement.click();
			},
		);

		this._inputElement.addEventListener('change', () => {
			this._change();
		});

		this._removeElement.addEventListener('click', () => {
			this._remove();
		});
	}

	protected _change(): void {
		const payload = { cancel: false };
		this._fireEvent('change', payload);
		this._dispatchEvent('change', payload);
		if (payload.cancel === true) {
			return;
		}

		const reader = new FileReader();

		reader.onload = () => {
			this._previewElement.style.backgroundImage = `url(${reader.result})`;
		};

		reader.readAsDataURL(this._inputElement.files[0]);
		this._selectedFile = this._inputElement.files[0];
		this._lastMode = 'new';

		this._element.classList.add('changed');
		this._removeElement.classList.remove('hidden');
		this._element.classList.remove('empty');

		this._fireEvent('changed');
		this._dispatchEvent('changed');
	}

	protected _remove(): void {
		const payload = { cancel: false };
		this._fireEvent('remove', payload);
		this._dispatchEvent('remove', payload);
		if (payload.cancel === true) {
			return;
		}

		this._element.classList.remove('empty');
		this._element.classList.remove('changed');

		if (this._lastMode == 'new') {
			if (this._previewUrl == '')
				this._removeElement.classList.add(
					this._getOption('hiddenClass') as string,
				);

			if (this._previewUrl) {
				this._previewElement.style.backgroundImage = `url(${this._previewUrl})`;
			} else {
				this._previewElement.style.backgroundImage = 'none';
				this._element.classList.add('empty');
			}

			this._inputElement.value = '';
			this._hiddenElement.value = '';
			this._selectedFile = null;

			this._lastMode = 'saved';
		} else if (this._lastMode == 'saved') {
			if (this._previewUrl == '')
				this._removeElement.classList.add(
					this._getOption('hiddenClass') as string,
				);

			this._previewElement.style.backgroundImage = 'none';
			this._element.classList.add('empty');

			this._hiddenElement.value = '1';
			this._inputElement.value = '';
			this._selectedFile = null;

			this._lastMode = 'placeholder';
		} else if (this._lastMode == 'placeholder') {
			if (this._previewUrl == '')
				this._removeElement.classList.add(
					this._getOption('hiddenClass') as string,
				);

			if (this._previewUrl) {
				this._previewElement.style.backgroundImage = `url(${this._previewUrl})`;
			} else {
				this._element.classList.add('empty');
			}

			this._inputElement.value = '';
			this._hiddenElement.value = '';
			this._selectedFile = null;

			this._lastMode = 'saved';
		}

		this._fireEvent('remove');
		this._dispatchEvent('remove');
	}

	protected _update() {
		if (this._previewElement.style.backgroundImage) {
			this._setPreviewUrl(this._previewElement.style.backgroundImage);
			this._removeElement.classList.remove(
				this._getOption('hiddenClass') as string,
			);
			this._lastMode = 'saved';
		} else {
			this._removeElement.classList.add(
				this._getOption('hiddenClass') as string,
			);
			this._element.classList.add('empty');
			this._lastMode = 'placeholder';
		}
	}

	protected _getPreviewUrl(): string {
		return this._previewUrl;
	}

	protected _setPreviewUrl(url: string): void {
		this._previewUrl = url.replace(/(url\(|\)|")/g, '');
	}

	public isEmpty(): boolean {
		return this._selectedFile === null;
	}

	public isChanged(): boolean {
		return this._selectedFile !== null;
	}

	public remove(): void {
		this._remove();
	}

	public update(): void {
		this._update();
	}

	public setPreviewUrl(url: string): void {
		this._setPreviewUrl(url);
	}

	public getPreviewUrl(): string {
		return this._getPreviewUrl();
	}

	public getSelectedFile(): File | null {
		return this._selectedFile;
	}

	public static getInstance(element: HTMLElement): KTImageInput | null {
		if (!element) return null;

		if (KTData.has(element, 'image-input')) {
			return KTData.get(element, 'image-input') as KTImageInput;
		}

		if (element.getAttribute('data-kt-image-input')) {
			return new KTImageInput(element);
		}

		return null;
	}

	public static getOrCreateInstance(
		element: HTMLElement,
		config?: KTImageInputConfigInterface,
	): KTImageInput {
		return this.getInstance(element) || new KTImageInput(element, config);
	}

	public static createInstances(): void {
		const elements = document.querySelectorAll('[data-kt-image-input]');

		elements.forEach((element) => {
			new KTImageInput(element as HTMLElement);
		});
	}

	public static init(): void {
		KTImageInput.createInstances();
	}
}

if (typeof window !== 'undefined') {
	window.KTImageInput = KTImageInput;
}
