import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
	Button as SemanticButton,
	Icon as SemanticIcon,
	Label as SemanticLabel
} from 'semantic-ui-react';
import Filter from './Filter';
import Numbro from '../Numbro';

import * as styles from './Style.less';

export default class FilterAdvanced extends Component {
	static propTypes = {
		properties: PropTypes.array.isRequired,
		options: PropTypes.object,
		filters: PropTypes.array,
		onChange: PropTypes.func.isRequired,
		maxDate: PropTypes.number
	};

	static defaultProps = {
		options: null,
		filters: [],
		maxDate: 0
	};

	constructor(props) {
		super(props);

		this.state = {
			filters: []
		};
	}

	componentWillMount() {
		this.reset();
	}

	onReset() {
		this.reset();
	}

	onAdd() {
		let filters = [...this.state.filters];
		const property = this.props.properties[0];

		const filter = {
			index: -1,
			operand: Filter.types[property.type][0],
			property: property.value
		};

		filters.unshift({ ...filter, valid: this.validateFilter(filter) });
		filters = filters.map((f, index) => ({ ...f, index }));

		this.setState(() => ({
			filters,
			showSave: true
		}));
	}

	onChange(filter) {
		const filters = [...this.state.filters];
		filters.splice(filter.index, 1, filter);

		this.setState(() => ({
			filters,
			showSave: this.filtersChanged(filters)
		}));
	}

	onRemove(index) {
		let { filters } = this.state;
		filters.splice(index, 1);
		filters = filters.map((f, i) => ({ ...f, index: i }));

		this.setState(() => ({
			filters,
			showSave: this.filtersChanged(filters)
		}));
	}

	onSave() {
		const filters = this.state.filters.map((filter, index) => {
			const property = this.props.properties.find(prop => prop.value === filter.property);
			let { value } = filter;
			if (property.type === 'percent') {
				const values = value.split(',');
				value = values.map(v => Numbro.format(parseFloat(v.trim()) / 100, '0[.]00')).join(',');
			}
			return {
				...filter,
				index,
				value
			};
		});

		this.props.onChange(filters);
	}

	reset() {
		const filters = [];
		this.props.filters.forEach((filter, index) => {
			const property = this.props.properties.find(prop => prop.value === filter.property);
			if (property) {
				let { value } = filter;
				if (property.type === 'percent') {
					const values = value.split(',');
					value = values.map(v => Numbro.format(parseFloat(v) * 100, '0,0')).join(', ');
				}
				filters.push({
					...filter,
					index,
					value
				});
			}
		});
		this.setState({
			filters,
			showRail: false,
			showSave: false
		});
	}

	filtersChanged(filters) {
		if (filters.length !== this.props.filters.length) {
			return true;
		}

		return filters.some((f, i) => {
			const originalFilter = this.props.filters[i];

			return f.property !== originalFilter.property
				|| f.operand !== originalFilter.operand
				|| f.value !== originalFilter.value;
		});
	}

	filterExists(filter) {
		const found = this.state.filters.find((f) => {
			return f.property === filter.property
				&& f.operand === filter.operand
				&& f.index !== filter.index;
		});

		return found !== undefined;
	}

	validateFilter(filter) {
		if (this.filterExists(filter)) {
			return false;
		}

		if (!filter.value || filter.value.length === 0) {
			return false;
		}

		if (Filter.rangeValue(filter.operand) && !/^\w+\s*,\s*\w+$/.test(filter.value)) {
			return false;
		}

		// if (filter.operand === 'in' || filter.operand === 'nin') {
		// 	let wrappingValues = false;
		// 	let values;

		// 	if (filter.type === 'enum' || filter.value.indexOf('"') !== -1) {
		// 		wrappingValues = true;
		// 		values = filter.value.split('",');
		// 	} else {
		// 		values = filter.value.split(',');
		// 	}

		// 	const filteredValues = [];

		// 	values.forEach((value) => {
		// 		const filteredValue = value.trim().replace(/^"|"$/g, '').trim();

		// 		if (filteredValue.length) {
		// 			filteredValues.push(filteredValue);
		// 		}
		// 	});

		// 	if (filteredValues.length > 0) {
		// 		filter.value = wrappingValues ? filteredValues.map(v => `"${v}"`).join(',') : filteredValues.join(',');

		// 		return true;
		// 	}

		// 	return false;
		// }

		return true;
	}

	render() {
		const {
			maxDate,
			properties,
			options,
			onChange
		} = this.props;

		const filters = this.state.filters.map(f => ({ ...f, valid: this.validateFilter(f) }));
		const valid = filters.every(f => f.valid);

		const filterComponents = filters.map((filter) => {
			return (
				<Filter
					maxDate={maxDate}
					key={`f${filter.index}`}
					properties={properties}
					options={options}
					property={filter.property}
					value={filter.value}
					operand={filter.operand}
					onChange={val => this.onChange(val)}
					onRemove={val => this.onRemove(val)}
					index={filter.index}
					valid={filter.valid}
				/>
			);
		});

		return (
			<>
				<div className={styles.FilterAdvanced}>
					<SemanticIcon name="filter" />
					<SemanticLabel
						color={filters.length ? 'blue' : 'grey'}
						onClick={() => {
							this.setState(state => ({
								showRail: state.showSave ? true : !state.showRail
							}));
						}}
					>
						{
							filters.length === 0 ? (
								'No Filters'
							) : (
								<>
									{filters.length} {filters.length === 1 ? 'Filter' : 'Filters'}
									<SemanticIcon
										name="times"
										onClick={() => onChange([])}
									/>
								</>
							)
						}
					</SemanticLabel>
					{
						this.state.showSave && (
							<>
								<SemanticButton
									color="green"
									disabled={!valid}
									onClick={() => this.onSave()}
								>
									Save Changes
								</SemanticButton>
								<SemanticButton
									color="red"
									onClick={() => this.onReset()}
								>
									Discard Changes
								</SemanticButton>
							</>
						)
					}
				</div>
				<div
					className={`${styles.Rail} ${this.state.showRail ? 'visible' : 'hidden'}`}
				>
					<SemanticButton>
						<SemanticIcon name="add square" onClick={() => this.onAdd()} />
					</SemanticButton>
					<div className={styles.Labels}>
						{filterComponents}
					</div>
				</div>
			</>
		);
	}
}
