import React from 'react';
import update from 'immutability-helper';
import block from 'bem-block';
import cx from 'classnames';
import ConnectionMap from './map/connection-map.class';
import { IAvailableCountryFilter, IAvailableFilters } from './data';
import SVGIconInfo from './svg/icon-info.svg';
import SVGIconTick from './svg/tick.svg';
import SVGIconArrowBack from './svg/arrow-back.svg';
import findIndex from 'lodash/findIndex';

interface ISidebarFilterConfig {
	label: string;
	filterName: string;
	filterPath: Array<string>;
	valueIfChecked: any;
	valueIfUnChecked: any;
	hasInfo?: boolean;
	infoText?: string;
}

interface IFilterSidebarProps {
	map: ConnectionMap;
	availableFilters: IAvailableFilters;
	onBackAction: () => void;
}

interface IFilterSidebarState {
	filters: {
		[x: string]: boolean;
	};
	showInfo: {
		[x: string]: boolean;
	};
	selectedCountries: Array<IAvailableCountryFilter>;
	selectedCountryIndex: number;
}

const bem = block('sidebar');
const isListedFilters = [
	{
		label: 'All',
		filterName: 'isListedNone',
		filterValue: null
	},
	{
		label: 'Listed',
		filterName: 'isListedTrue',
		filterValue: true
	},
	{
		label: 'Private',
		filterName: 'isListedFalse',
		filterValue: false
	}
];

export default class FilterSideBar extends React.Component<
	IFilterSidebarProps,
	IFilterSidebarState
> {
	state = {
		filters: {
			isListedNone: true
		},
		showInfo: {},
		selectedCountries: [],
		selectedCountryIndex: -1
	};

	private _handleFilterCheckboxChange(
		{
			filterName,
			filterPath,
			valueIfChecked = true,
			valueIfUnChecked = false
		}: ISidebarFilterConfig,
		event: React.ChangeEvent<HTMLInputElement>
	) {
		const checked = event.target.checked;
		this.setState(oldState =>
			update(oldState, {
				filters: {
					$merge: { [filterName]: checked }
				}
			})
		);

		this.props.map.setFilter(
			filterPath,
			checked ? valueIfChecked : valueIfUnChecked
		);
	}

	private _handleListedFilterRadioChange(
		{ filterName, filterValue },
		event: React.ChangeEvent<HTMLInputElement>
	) {
		const checked = event.target.checked;

		const filterUpdate = isListedFilters.reduce((prev, curr) => {
			prev[curr.filterName] = false;
			return prev;
		}, {});

		filterUpdate[filterName] = checked;

		this.setState(
			oldState =>
				update(oldState, {
					filters: {
						$merge: filterUpdate
					}
				}),
			() => {
				this.props.map.setFilter(['company', 'isListed'], filterValue);
			}
		);
	}

	private _handleCountrySelectChange(
		event: React.ChangeEvent<HTMLSelectElement>
	) {
		if (parseInt(event.target.value, 10) >= 0) {
			const selectedCountry = this.props.availableFilters.countries[
				event.target.value
			];

			this.setState(oldState =>
				update(oldState, {
					selectedCountries: {
						$push: [selectedCountry]
					}
				})
			);

			this.props.map.setFilter(
				['country_iso3'],
				selectedCountry.country_iso3,
				selectedCountry.country_iso3
			);
		}
	}

	private _handleSelectedCountryRemove(
		selectedCountry: IAvailableCountryFilter
	) {
		this.setState(oldState =>
			update(oldState, {
				selectedCountries: {
					$splice: [
						[
							oldState.selectedCountries.findIndex(
								country =>
									country.country_iso3 ===
									selectedCountry.country_iso3
							),
							1
						]
					]
				}
			})
		);

		this.props.map.setFilter(
			['country_iso3'],
			null,
			selectedCountry.country_iso3
		);
	}

	private _renderCheckboxFromFilter = (
		filter: ISidebarFilterConfig,
		changeFn?: (
			filter: ISidebarFilterConfig,
			event: React.ChangeEvent<HTMLInputElement>
		) => void
	) => (
		<label htmlFor={filter.filterName}>
			<span className={bem('checkbox-container')}>
				<input
					type="checkbox"
					name={filter.filterName}
					id={filter.filterName}
					checked={!!this.state.filters[filter.filterName]}
					className={bem('checkbox')}
					onChange={
						changeFn
							? changeFn.bind(this, filter)
							: this._handleFilterCheckboxChange.bind(
									this,
									filter
							  )
					}
				/>
				<SVGIconTick className={cx(bem('checkbox-tick'), 'icon')} />
			</span>
			{filter.label}
		</label>
	);

	private _clearAllFilters(event: React.MouseEvent<HTMLButtonElement>) {
		this.props.map.clearFilters();
		this.setState(oldState => ({
			filters: {
				isListedNone: true
			},
			selectedCountries: [],
			selectedCountryIndex: -1
		}));
	}

	private _isFiltered = () =>
		this.state.filters['isListedTrue'] ||
		this.state.filters['isListedFalse'] ||
		(Object.keys(this.state.filters).length > 1 ||
			this.state.selectedCountries.length > 0);

	render() {
		const filters = [
			{
				label: 'scoutAsia companies',
				filterName: 'isScoutCompany',
				filterPath: ['isScoutCompany'],
				valueIfChecked: true,
				valueIfUnChecked: null,
				hasInfo: true,
				infoText:
					'scoutAsia companies have revenues over $10m, or at least 150 employees, and operate within 24 Asian countries.'
			}
		];

		return (
			<aside className={bem()}>
				<button
					className={bem('back')}
					onClick={this.props.onBackAction}
				>
					<SVGIconArrowBack className="icon" />
					<span>Back</span>
				</button>
				<div className={bem('title')}>Operational structure</div>

				<div
					className={cx(bem('item'), bem('item', { filters: true }))}
				>
					<h2 className={bem('item-title')}>Company attributes</h2>

					<ul className="list-unstyled">
						{filters.map(filter => (
							<li
								key={filter.filterName}
								className={bem('filter-item')}
							>
								<div className={bem('filter-item-content')}>
									{this._renderCheckboxFromFilter(filter)}
								</div>
								{filter.hasInfo ? (
									<div className={bem('info-text')}>
										<SVGIconInfo
											className={cx(
												bem('info-icon'),
												bem('info-scout-company')
											)}
										/>
										{filter.infoText}
									</div>
								) : null}
							</li>
						))}
					</ul>
				</div>

				<div
					className={cx(
						bem('item'),
						bem('item', { countries: true })
					)}
				>
					<h2 className={bem('item-title')}>Ownership</h2>
					<ul className="list-unstyled">
						{isListedFilters.map(filter => (
							<li
								key={filter.filterName}
								className={bem('radio-container')}
							>
								<label htmlFor={filter.filterName}>
									<input
										type="radio"
										name={'isListed'}
										id={filter.filterName}
										value={filter.filterName}
										checked={
											!!this.state.filters[
												filter.filterName
											]
										}
										onChange={this._handleListedFilterRadioChange.bind(
											this,
											filter
										)}
										className={bem('radio')}
									/>
									<span className={bem('radio-label')}>
										{filter.label}
									</span>
								</label>
							</li>
						))}
					</ul>
				</div>

				<div
					className={cx(
						bem('item'),
						bem('item', { countries: true })
					)}
				>
					<h2 className={bem('item-title')}>Countries & regions</h2>
					<div
						className={cx(
							bem('selected-items'),
							bem('selected-items', {
								active: this.state.selectedCountries.length
							})
						)}
					>
						{this.state.selectedCountries.map(selectedCountry => (
							<div
								className={bem('selected-item-token')}
								key={selectedCountry.country_iso3}
								onClick={this._handleSelectedCountryRemove.bind(
									this,
									selectedCountry
								)}
							>
								<span
									className={bem('selected-item-token-name')}
								>
									{selectedCountry.country}
								</span>
								<div
									className={bem(
										'selected-item-token-remove'
									)}
								>
									x
								</div>
							</div>
						))}
					</div>
					<div className={bem('select-container')}>
						<select
							className={bem('select')}
							onChange={this._handleCountrySelectChange.bind(
								this
							)}
							value={this.state.selectedCountryIndex}
						>
							<option value={-1}>
								Select a Country or region
							</option>
							{this.props.availableFilters.countries.map(
								(filterCountry, index) => (
									<option
										key={index}
										value={index}
										disabled={
											findIndex(
												this.state.selectedCountries,
												country =>
													country.country_iso3 ===
													filterCountry.country_iso3
											) > -1
										}
									>
										{filterCountry.country}
									</option>
								)
							)}
						</select>
					</div>
				</div>

				<div
					className={cx(bem('item'), bem('item', { actions: true }))}
				>
					<button
						className={bem('clear')}
						onClick={this._clearAllFilters.bind(this)}
						disabled={!this._isFiltered.bind(this)()}
					>
						Clear filters
					</button>
				</div>
			</aside>
		);
	}
}
