<template>
	<ResizeObserver
		:breakpoints="[{bp: 'md', width: 500}]"
	>
		<template v-slot="{ bp }">
			<div :class="bp === 'md' || columnView? $style.grid : $style.gridMulti">
				<div
					v-for="(input) in filteredInputs"
					:key="input.name"
				>
					<n8n-text color="text-base" v-if="input.properties.type === 'info'" tag="div" align="center">
						{{input.properties.label}}
					</n8n-text>
					<n8n-form-input
						v-else
						v-bind="input.properties"
						:value="values[input.name]"
						:showValidationWarnings="showValidationWarnings"
						@input="(value) => onInput(input.name, value)"
						@validate="(value) => onValidate(input.name, value)"
						@enter="onSubmit"
					/>
				</div>
			</div>
		</template>
	</ResizeObserver>
</template>

<script lang="ts">
import Vue from 'vue';
import N8nFormInput from '../N8nFormInput';
import { IFormInputs } from '../../types';
import ResizeObserver from '../ResizeObserver';

export default Vue.extend({
	name: 'n8n-form-inputs',
	components: {
		N8nFormInput,
		ResizeObserver,
	},
	props: {
		inputs: {
			type: Array,
			default() {
				return [[]];
			},
		},
		eventBus: {
			type: Vue,
		},
		columnView: {
			type: Boolean,
		},
	},
	data() {
		return {
			showValidationWarnings: false,
			values: {} as {[key: string]: any},
			validity: {} as {[key: string]: boolean},
		};
	},
	mounted() {
		(this.inputs as IFormInputs).forEach((input: IFormInput) => {
			if (input.hasOwnProperty('initialValue')) {
				Vue.set(this.values, input.name, input.initialValue);
			}
		});

		if (this.eventBus) {
			this.eventBus.$on('submit', this.onSubmit);
		}
	},
	computed: {
		filteredInputs(): IFormInput[] {
			return this.inputs.filter((input: IFormInput) => typeof input.shouldDisplay === 'function'? input.shouldDisplay(this.values): true);
		},
		isReadyToSubmit(): boolean {
			for (let key in this.validity) {
				if (!this.validity[key]) {
					return false;
				}
			}

			return true;
		},
	},
	methods: {
		onInput(name: string, value: any) {
			this.values = {
				...this.values,
				[name]: value,
			};
			this.$emit('input', {name, value});
		},
		onValidate(name: string, valid: boolean) {
			Vue.set(this.validity, name, valid);
		},
		onSubmit() {
			this.showValidationWarnings = true;
			if (this.isReadyToSubmit) {
				const toSubmit = this.filteredInputs.reduce((accu, input: IFormInput) => {
					if (this.values[input.name]) {
						accu[input.name] = this.values[input.name];
					}
					return accu;
				}, {});
				this.$emit('submit', toSubmit);
			}
		},
	},
	watch: {
		isReadyToSubmit(ready: boolean) {
			this.$emit('ready', ready);
		},
	},
});
</script>

<style lang="scss" module>
.grid {
	display: grid;
	grid-row-gap: var(--spacing-s);
	grid-column-gap: var(--spacing-2xs);
}

.gridMulti {
	composes: grid;
	grid-template-columns: repeat(2, 1fr);
}

</style>