import type { VNode } from 'vue';
import type { ILocalizedText } from '../../common/localized-text';
import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item';
import type { FormItemWrapperArgs, HintType, MarginType } from '../form/form-item-wrapper';
import type { TranslateGetRequest, TranslateGetResponse } from './translate';
import { Prop, toNative } from 'vue-facing-decorator';
import PowerduckState from '../../app/powerduck-state';
import TsxComponent, { Component } from '../../app/vuetsx';
import { Language } from '../../common/enums/language';
import LocalizedValueHelper from '../../common/localized-value-helper';
import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
import { LanguageUtils } from '../../common/utils/language-utils';
import { PortalUtils } from '../../common/utils/utils';
import Button from '../button/button';
import { ButtonLayout } from '../button/button-layout';
import FormItemWrapper from '../form/form-item-wrapper';
import Modal, { ModalSize } from '../modal/modal';
import ModalBody from '../modal/modal-body';
import ModalFooter from '../modal/modal-footer';
import globalIcon from './img/global.png';
import Translate from './translate';
import './css/localized-string-input.css';

interface LocalizedStringInputArgs extends FormItemWrapperArgs {
	value: ILocalizedText;
	changed: (e: ILocalizedText) => void;
	supportedLanguages?: Language[];
	placeholder?: string;
	translatable?: boolean;
	translateApiMethod?: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
}

@Component
class LocalizedStringInputComponent extends TsxComponent<LocalizedStringInputArgs> implements LocalizedStringInputArgs {
	@Prop() label!: string | VNode;
	@Prop() labelButtons!: DropdownButtonItemArgs[];
	@Prop() subtitle!: string;
	@Prop() value!: ILocalizedText;
	@Prop() changed: (e: ILocalizedText) => void;
	@Prop() supportedLanguages?: Language[];
	@Prop() marginType?: MarginType;
	@Prop() maxWidth?: number;
	@Prop() placeholder!: string;
	@Prop() mandatory!: boolean;
	@Prop() wrap!: boolean;
	@Prop() showClearValueButton!: boolean;
	@Prop() cssClass: string;
	@Prop() hint: string;
	@Prop() hintType!: HintType;
	@Prop() appendIcon: string;
	@Prop() prependIcon: string;
	@Prop({ default: false }) translatable: boolean;
	@Prop() translateApiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
	@Prop() appendClicked: () => void;
	@Prop() prependClicked: () => void;
	currentValue: ILocalizedText = null;
	modalWillShow: boolean = false;
	uuid: string = `lsw-${PortalUtils.randomString(10)}`;

	raiseChangeEvent(newValue: ILocalizedText): void {
		this.populateValidationDeclaration();

		if (this.changed != null) {
			this.changed(newValue);
		}
	}

	isAllSame(): boolean {
		if (this.value != null) {
			const langList = LanguageUtils.getLanguageList();
			const skValue = LocalizedValueHelper.getValue(this.value, Language.sk);

			for (let i = 0, len = langList.length; i < len; i++) {
				if (LocalizedValueHelper.getValue(this.value, langList[i].id) != skValue) {
					return false;
				}
			}
		}

		return true;
	}

	hasSomeValue(): boolean {
		return !isNullOrEmpty(LocalizedValueHelper.getValue(this.value, Language.sk));
	}

	private getModalContext(): HTMLElement | null {
		return document.getElementById(this.uuid);
	}

	showInputModal(): void {
		this.modalWillShow = true;
		this.currentValue = JSON.parse(JSON.stringify(this.value || {}));

		this.$nextTick(() => {
			(this.$refs.dlgLocalizedString as typeof Modal.prototype).show({
				onShown: () => {
					setTimeout(() => {
						const ctx = this.getModalContext();
						let input = ctx?.querySelector<HTMLElement>(`.lsi-main-input[data-inv-lang="${PowerduckState.getCurrentLanguage()}"]`);
						if (input == null) {
							input = Array.from(ctx?.querySelectorAll<HTMLElement>('.lsi-main-input') ?? [])
								.find(el => el.offsetParent != null || el.getClientRects().length > 0) ?? null;
						}

						input?.focus();
					}, 15);
				},
			});
		});
	}

	handleModalValueChange(newValue: string, lang: { id: Language }) {
		const value = this.currentValue;
		const propName = lang.id;
		if (isNullOrEmpty(newValue)) {
			value[propName] = null;
		} else {
			value[propName] = newValue;
		}

		this.getModalContext()
			?.querySelectorAll<HTMLInputElement>('[data-inv-lang]')
			.forEach((el) => {
				const currentVal = el.value;

				if (currentVal == null || currentVal.length == 0) {
					const language: Language = el.getAttribute('data-inv-lang') as any;
					const lsValue = LocalizedValueHelper.getValue(value, language) || '';
					el.setAttribute('placeholder', lsValue);
				}
			});
	}

	render(h) {
		return (
			<div class={this.cssClass}>
				<FormItemWrapper
					label={this.label}
					mandatory={this.mandatory}
					wrap={this.wrap}
					appendIcon={this.appendIcon}
					prependIcon={this.prependIcon}
					hint={this.hint}
					hintType={this.hintType}
					appendClicked={this.appendClicked}
					prependClicked={this.prependClicked}
					marginType={this.marginType}
					maxWidth={this.maxWidth}
					validationState={this.validationState}
					labelButtons={this.labelButtons}
					subtitle={this.subtitle}
					showClearValueButton={this.showClearValueButton}
				>
					{this.renderInput(h)}
				</FormItemWrapper>
				{this.modalWillShow && this.renderModal(h)}
			</div>
		);
	}

	renderInput(h) {
		const allSame = this.isAllSame();
		const hasValue = this.hasSomeValue();

		if (allSame && !hasValue) {
			return this.renderInputPlaceholder(h);
		} else if (allSame) {
			return this.renderInputGlobalValue(h);
		} else {
			return this.renderInputMultipleValues(h);
		}
	}

	renderInputPlaceholder(h) {
		return (
			<div class={`${PowerduckState.getFormControlCssClass()} localized-input-wrap lii-placeholder localized-input`} onClick={_e => this.showInputModal()}>
				{this.placeholder}
			</div>
		);
	}

	renderInputGlobalValue(h) {
		return (
			<div class={`${PowerduckState.getFormControlCssClass()}  localized-input`} onClick={_e => this.showInputModal()}>
				<img src={globalIcon} />
                &nbsp;
				{LocalizedValueHelper.getValue(this.value, Language.sk)}
			</div>
		);
	}

	renderInputMultipleValues(h) {
		return (
			<div class={`${PowerduckState.getFormControlCssClass()} localized-input-wrap lii-more localized-input`} onClick={_e => this.showInputModal()}>
				{LanguageUtils.getLanguageList().map((lang) => {
					if (this.supportedLanguages != null && !(this.supportedLanguages.includes(lang.id))) {
						return null;
					}

					let langValue = this.value[lang.id];
					const hasValue = !isNullOrEmpty(langValue);
					langValue = hasValue ? langValue : LocalizedValueHelper.getValue(this.value, lang.id);

					return (
						<div class={`localized-input-item${hasValue ? '' : ' lii-auto'}`}>
							<img src={LanguageUtils.getLanguageFlagUrl(lang.flag)} />
                            &nbsp;
							{langValue}
						</div>
					);
				})}
			</div>
		);
	}

	renderModal(h) {
		return (
			<Modal ref="dlgLocalizedString" title={this.label} size={ModalSize.Large}>
				{this.currentValue != null && (
					<ModalBody>
						<div id={this.uuid}>
							{LanguageUtils.getLanguageList().map((lang) => {
								if (this.supportedLanguages != null && !(this.supportedLanguages.includes(lang.id))) {
									return null;
								}

								let langValue = this.currentValue[lang.id];
								const hasValue = !isNullOrEmpty(langValue);
								langValue = hasValue ? langValue : LocalizedValueHelper.getValue(this.currentValue, lang.id);

								return (
									<div class="row align-items-end lsi-form-group">
										<label class="col-md-3 col-form-label lsi-label">
											<span class="lsi-text">
												{lang.text}
&nbsp;&nbsp;
											</span>
											<img class="lsi-icon" src={LanguageUtils.getLanguageFlagUrl(lang.flag)} />
										</label>
										<div class="col-md-9">
											<div class="d-flex justify-content-end">
												{this.translatable !== false && (
													<Translate
														value={this.currentValue}
														currentLangId={lang.id}
														langArr={LanguageUtils.getLanguageList()}
														changeValue={(langId, value) => {
															this.handleModalValueChange(value, { id: langId });
															this.$forceUpdate();
														}}
														getActualValue={(langId, value) => value[langId]}
														apiMethod={this.translateApiMethod}
													/>
												)}
											</div>
											<div class="form-group maxwidth-input ">
												<input
													type="text"
													data-inv-lang={lang.id}
													placeholder={hasValue ? '' : langValue}
													class={`${PowerduckState.getFormControlCssClass()} lsi-main-input`}
													onChange={e => this.handleModalValueChange(e.target.value, lang)}
													onKeyup={e => this.handleModalValueChange(e.target.value, lang)}
													value={hasValue ? langValue : null}
												/>
											</div>
										</div>
									</div>
								);
							})}
						</div>
					</ModalBody>
				)}
				<ModalFooter>
					<Button dismissModal={true} text={PowerduckState.getResourceValue('cancel')} layout={ButtonLayout.Default} clicked={() => { }} />
					<Button
						dismissModal={true}
						text="OK"
						layout={ButtonLayout.Primary}
						clicked={() => {
							this.raiseChangeEvent(this.currentValue);
						}}
					/>
				</ModalFooter>
			</Modal>
		);
	}
}

const LocalizedStringInput = toNative(LocalizedStringInputComponent);
export default LocalizedStringInput;
