import type { ValidationRuleset } from '../../common/static-wrappers/interfaces/validation-interface';
import { Prop, toNative } from 'vue-facing-decorator';
import { TsxComponentExtendedBase } from '../../app/vuestsx-extended';
import { Component } from '../../app/vuetsx';
import { ValidationBuilder } from '../../common/validation';
import Button from './../button/button';
import { ButtonLayout, ButtonSize } from './../button/button-layout';
import FlexContainer from './../form/flex-container';
import FlexFormItem from './../form/form-item-flex';
import FormItemWrapper from './../form/form-item-wrapper';
import TextBox, { TextBoxTextType } from './../input/textbox';

export interface VideoUrls {
	videoUrls: string[];
}

interface VideoUrlContainerArgs {
	videoModel: VideoUrls;
	label?: string;
}

interface VideoUrlItemArgs {
	value: string;
	isFirst: boolean;
	addNewClicked: () => void;
	removeClicked: () => void;
	changed: (newValue: string) => void;
}

const videoUrlsValidations: ValidationRuleset<VideoUrlsContainerComponent> = {
	videoModel: new ValidationBuilder().required().build(),
};

const videoUrlItemValidations: ValidationRuleset<VideoUrlItemComponent> = {
	value: new ValidationBuilder().url().build(),
};

class TsxComponentExtended<P> extends TsxComponentExtendedBase<P> {

}

@Component({ validations: videoUrlsValidations })
class VideoUrlsContainerComponent extends TsxComponentExtended<VideoUrlContainerArgs> implements VideoUrlContainerArgs {
	@Prop() label?: string;
	@Prop() videoModel: VideoUrls;

	mounted() {
		this.prepareValue();
	}

	prepareValue() {
		if (this.videoModel.videoUrls == null) {
			this.videoModel.videoUrls = [];
		}

		if (this.videoModel.videoUrls.length == 0) {
			this.videoModel.videoUrls.push(null);
		}
	}

	getVideoUrlItemControl(index: number): VideoUrlItemComponent {
		return this.$refs[`videoUrlItem${index}`] as VideoUrlItemComponent;
	}

	resetValidation() {
		if (this.videoModel.videoUrls != null) {
			this.videoModel.videoUrls.forEach((url, i) => {
				try {
					this.getVideoUrlItemControl(i).resetValidation();
				} catch (e) {}
			});
		}

		super.resetValidation();
	}

	async validate(showErrorMessage) {
		let valid = await super.validate(showErrorMessage);
		if (this.videoModel.videoUrls != null) {
			for (let i = 0; i < this.videoModel.videoUrls.length; i++) {
				var itemResult: boolean;
				try {
					itemResult = await this.getVideoUrlItemControl(i).validate(false);
				} catch (e) {
					itemResult = true;
				}

				if (itemResult == false) {
					valid = false;
				}
			}
		}

		return valid;
	}

	addNewVideoUrl() {
		this.videoModel.videoUrls.push(null);
	}

	removeVideoUrl(index: number): void {
		this.videoModel.videoUrls.splice(index, 1);
	}

	render(h) {
		if (this.videoModel.videoUrls == null) {
			return null;
		}

		return (
			<FormItemWrapper label={this.label}>
				{this.videoModel.videoUrls.map((url, i) => (
					<VideoUrlItem
						ref={`videoUrlItem${i}`}
						value={url}
						isFirst={i == 0}
						addNewClicked={() => {
							this.addNewVideoUrl();
						}}
						removeClicked={() => {
							this.removeVideoUrl(i);
						}}
						changed={(e) => {
							this.videoModel.videoUrls[i] = e;
						}}
					/>
				))}
			</FormItemWrapper>
		);
	}
}

export const VideoUrlsContainer = toNative(VideoUrlsContainerComponent);

@Component({ validations: videoUrlItemValidations })
class VideoUrlItemComponent extends TsxComponentExtended<VideoUrlItemArgs> implements VideoUrlItemArgs {
	@Prop() value!: string;
	@Prop() isFirst: boolean;
	@Prop() addNewClicked: () => void;
	@Prop() removeClicked: () => void;
	@Prop() changed: (newValue: string) => void;

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

	render(h) {
		return (
			<FlexContainer fullWidthOnMobile={true}>
				<FlexFormItem flexFill={true}>
					<TextBox
						wrap={false}
						mandatory={true}
						placeholder="Video URL"
						label={null}
						value={this.value}
						textType={TextBoxTextType.Url}
						validationState={this.validationStateOf(this.v$.value)}
						changed={(e) => {
							this.handleChanged(e);
						}}
					/>
				</FlexFormItem>
				<FlexFormItem flexFill={false} width={50}>
					<div>
						{this.isFirst && (
							<div>
								<Button
									layout={ButtonLayout.Default}
									outlined={true}
									size={ButtonSize.Small}
									iconButton={true}
									icon="icon icon-plus"
									clicked={() => {
										this.addNewClicked();
									}}
								/>
							</div>
						)}

						{!this.isFirst && (
							<Button
								layout={ButtonLayout.Danger}
								outlined={true}
								size={ButtonSize.Small}
								iconButton={true}
								icon="icon icon-close"
								clicked={() => {
									this.removeClicked();
								}}
							/>
						)}
					</div>
				</FlexFormItem>
			</FlexContainer>
		);
	}
}

export const VideoUrlItem = toNative(VideoUrlItemComponent);
