import type { VNode } from 'vue';
import type { Language } from '../../common/enums/language';
import type { ILocalizedText } from '../../common/localized-text';
import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item';
import type { FormItemWrapperArgs, 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 { LanguageUtils } from '../../common/utils/language-utils';
import FormItemWrapper from '../form/form-item-wrapper';
import { TabPage } from '../tabs/tab-page';
import Tabs, { TabsRenderMode } from '../tabs/tabs';
import Translate from './translate';
import WysiwygEditor from './wysiwig';

interface LocalizedStringInputArgs extends FormItemWrapperArgs {
	value: ILocalizedText;
	changed: (e: ILocalizedText) => void;
	supportedLanguages?: Language[];
	placeholder?: string;
	useFileManager?: boolean;
	itemId?: number;
	resizable?: boolean;
	translatable?: boolean;
	translateApiMethod?: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
	// When true (default), toggling Source view in one language tab carries
	// over to the others. Set to false to give each language its own toggle.
	shareSourceView?: boolean;
}

@Component
class LocalizedStringWysiwigComponent 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() useFileManager?: boolean;
	@Prop() itemId?: number;
	@Prop() mandatory!: boolean;
	@Prop() resizable!: boolean;
	@Prop() wrap!: boolean;
	@Prop() showClearValueButton!: boolean;
	@Prop() hint: string;
	@Prop() appendIcon: string;
	@Prop() prependIcon: string;
	@Prop() appendClicked: () => void;
	@Prop() prependClicked: () => void;
	@Prop({ default: false }) translatable: boolean;
	@Prop({ default: true }) shareSourceView: boolean;
	@Prop() translateApiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
	editorHeight: number = null;
	sharedHtmlView: boolean = false;

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

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

			this.changed(newValue);
		}
	}

	changeValue(lang: Language, newValue: string): void {
		const value = this.value || ({} as ILocalizedText);
		value[lang] = newValue;
		this.raiseChangeEvent(value);
	}

	onEditorResized(height: number): void {
		this.editorHeight = height;
	}

	getActualValue(lang: Language, value: ILocalizedText): string {
		if (value == null) {
			return null;
		}

		return value[lang];
	}

	render(h) {
		const langArr = this.supportedLanguages == null ? LanguageUtils.getLanguageList() : LanguageUtils.getLanguageList().filter(p => this.supportedLanguages.includes(p.id));
		let initialTabIndex = langArr.map(p => p.id).indexOf(PowerduckState.getCurrentLanguage());
		if (initialTabIndex == null || initialTabIndex < 1) {
			initialTabIndex = 0;
		}

		return (
			<FormItemWrapper
				cssClass={`localized-string-wysiwyg localized-input ${this.value != null ? 'hasval' : 'empty'}`}
				label={this.label}
				mandatory={this.mandatory}
				wrap={this.wrap}
				appendIcon={this.appendIcon}
				prependIcon={this.prependIcon}
				hint={this.hint}
				appendClicked={this.appendClicked}
				prependClicked={this.prependClicked}
				marginType={this.marginType}
				maxWidth={this.maxWidth}
				validationState={this.validationState}
				labelButtons={this.labelButtons}
				subtitle={this.subtitle}
				showClearValueButton={this.showClearValueButton}
			>
				<Tabs renderMode={TabsRenderMode.Normal} initialTabIndex={initialTabIndex}>
					{langArr.map(lang => (
						<TabPage
							navCaption={`<img src="${LanguageUtils.getLanguageFlagUrl(lang.flag)}"/>&nbsp;${lang.id.toUpperCase()}`}
							escapeCaption={false}
							icon={null}
							key={lang.id}
						>
							<WysiwygEditor
								key={lang.id}
								wrap={false}
								useFileManager={this.useFileManager}
								itemId={this.itemId}
								resizable={this.resizable}
								initialHeight={this.editorHeight}
								onResized={this.onEditorResized}
								label={null}
								value={this.getActualValue(lang.id, this.value)}
								htmlViewControlled={this.shareSourceView !== false ? this.sharedHtmlView : undefined}
								onHtmlViewChange={this.shareSourceView !== false ? ((v: boolean) => { this.sharedHtmlView = v; }) : undefined}
								changed={(e) => {
									this.changeValue(lang.id, e);
								}}
							/>
							{this.translatable !== false && (
								<Translate
									value={this.value}
									currentLangId={lang.id}
									langArr={langArr}
									changeValue={this.changeValue.bind(this)}
									getActualValue={(langId, value) => this.getActualValue(langId, value as ILocalizedText)}
									apiMethod={this.translateApiMethod}
								/>
							)}
						</TabPage>
					))}
				</Tabs>
			</FormItemWrapper>
		);
	}
}

const LocalizedStringWysiwig = toNative(LocalizedStringWysiwigComponent);
export default LocalizedStringWysiwig;
