import * as React from 'react';
import { ValidationRule, ValidationState } from '../../models/Validation';
import validationRules from '../../utils/validationRules';
import { validation, validationOnInit } from '../../utils/helper';
import { Colors } from '../../models/colors';

const tagManager = require('react-gtm-module');

export interface CommonInputProps {
	label?: string;
	type?: string;
	name?: string;
	value?: string;
	valid?: ValidationState;
	errorMessage?: string;
	placeholder?: string;
	notifyValidity?: (name: string, state: ValidationState, errorMessage?: React.ReactNode) => void;
	validationRules?: Array<ValidationRule>;
	onChange?: (name: string, value: string, e?: React.ChangeEvent<HTMLInputElement>) => void;
	onFocus?: (name: string, value: string, e?: React.FocusEvent<HTMLInputElement>) => void;
	onBlur?: (value: string, e?: React.FocusEvent<HTMLInputElement>) => void;
	onClick?: (e: React.MouseEvent<HTMLInputElement>) => void;
	onKeyDown?: (value: string, e: React.KeyboardEvent) => void;
	required?: boolean;
	doNotValidate?: boolean;
	automationName?: string;
	palette?: Colors;
	maxlength?: number;
	readOnly?: boolean;
	translator?: Function;
}

type CommonInputContainer = CommonInputProps & {
	render: (
		onChange: (value: string) => void,
		onBlur: (value: string) => void,
		onFocus: (value: string) => void
	) => JSX.Element;
};
class CommonInput extends React.PureComponent<CommonInputContainer> {
	constructor(props: CommonInputContainer) {
		super(props);

		let assignedValidationRules = Object.assign([], this.props.validationRules || []);

		if (this.props.required) {
			assignedValidationRules.unshift({ name: 'required' });
		}

		if (this.props.notifyValidity) {
			let { name, state, errorMessage } = validationOnInit(
				validationRules,
				assignedValidationRules,
				this.props.name,
				this.props.value,
				this.props.translator
			);
			this.props.notifyValidity(name, state, errorMessage);
		}
	}

	componentWillUnmount() {
		if (this.props.notifyValidity) {
			this.props.notifyValidity(this.props.name, ValidationState.None);
		}
	}

	onFocus = (value: string, e?: React.FocusEvent<HTMLInputElement>) => {
		if (this.props.onFocus) {
			this.props.onFocus(this.props.name, value, e);
		}
		tagManager.dataLayer({
			dataLayer: {
				event: 'focus-in',
				'input-name': name
			}
		});
	};

	onChange = (value: string, e?: React.FocusEvent<HTMLInputElement>) => {
		this.props.onChange(this.props.name, value);
	};

	onBlur = (value: string, e?: React.FocusEvent<HTMLInputElement>) => {
		tagManager.dataLayer({
			dataLayer: {
				event: 'focus-out',
				'input-name': name
			}
		});

		let assignedValidationRules = Object.assign([], this.props.validationRules || []);

		if (this.props.required) {
			assignedValidationRules.unshift({ name: 'required' });
		}
		if (!this.props.doNotValidate) {
			let { state, errorMessage } = validation(
				validationRules,
				assignedValidationRules,
				value,
				this.props.name,
				this.props.translator
			);
			if (
				this.props.notifyValidity &&
				(this.props.valid !== state || this.props.errorMessage !== errorMessage)
			) {
				this.props.notifyValidity(this.props.name, state, errorMessage);
			}
		}

		if (this.props.onBlur) {
			this.props.onBlur(value);
		}
	};

	render() {
		return this.props.render(this.onChange, this.onBlur, this.onFocus);
	}
}

export default CommonInput;
