// @flow
import * as React from 'react';
import {
	Container,
	Row,
	Col,
	Badge,
	Dropdown, DropdownMenu, DropdownItem, DropdownToggle,
	Input,
	Button,
} from 'reactstrap';

import { Link } from 'react-router-dom';

import { connect } from 'react-redux';

import * as Selectors from '@store/selectors.js';

import { pluralize } from '@helpers/beat';
import type { BeatEntity, BeatObject } from '@helpers/beat';

import SearchWorker from '@helpers/search.worker.js';

type Props = {
	entity: BeatEntity,
	data: BeatObject[],
};

type State = {
	searchResults: BeatObject[],
	resultsOpen: boolean,
};

class SearchBar extends React.PureComponent<Props, State> {
	constructor(props: Props){
		super(props);
	}

	state = {
		searchResults: [],
		resultsOpen: false,
	}

	searchWorker = null;

	componentDidMount = () => {
		this.searchWorker = new SearchWorker();
		this.searchWorker.onmessage = (m) => {
			this.setState(prevState => ({
				searchResults: m.data.slice(0, 5),
				resultsOpen: m.data.length > 0,
			}));
		};
		this.updateFuseInstance();
	}

	componentDidUpdate = (prevProps: Props) => {
		if(this.props.data !== prevProps.data){
			this.updateFuseInstance(this.props.data);
		}
	}

	updateFuseInstance = (data: BeatObject[] = this.props.data) => {
		if(!this.searchWorker)
			throw new Error(`searchWorker is not instantiated!`);
		this.searchWorker.postMessage(
			{
				type: 'dataChanged',
				payload: {
					data,
					options: {
						shouldSort: true,
						tokenize: true,
						threshold: 0.6,
						location: 0,
						distance: 100,
						maxPatternLength: 32,
						minMatchCharLength: 1,
						keys: ['name', 'contents.description', 'contents.#description'],
					}
				}
			}
		);
	}

	search = (str: string) => {
		if(!this.searchWorker)
			throw new Error(`searchWorker is not instantiated!`);
		this.searchWorker.postMessage(
			{
				type: 'search',
				payload: str
			}
		);
	}

	toggleResults = (val: boolean = !this.state.resultsOpen) => {
		this.setState({ resultsOpen: val });
	};

	render = () => {
		return (
			<Dropdown
				isOpen={this.state.resultsOpen}
				toggle={e => this.toggleResults(false)}
				style={{flex: 1}}
				className='ml-2 mr-2'
			>
				<DropdownToggle
					tag='span'
				>
					<Input
						onChange={e => {
							this.search(e.target.value);
						}}
						placeholder={`Search ${ pluralize(this.props.entity) }...`}
					/>
				</DropdownToggle>
				<DropdownMenu>
					{
						this.state.searchResults.map((r, i) =>
							<DropdownItem
								tag={Link}
								to={`/${ this.props.entity }/${ r.name }`}
								key={i}
							>
								{ r.name }
								{' '}
								<small className='text-muted'>
									{ r.contents.description || r.contents['#description'] || '' }
								</small>
							</DropdownItem>
						)
					}
				</DropdownMenu>
			</Dropdown>
		);
	}
}

const mapStateToProps = (state, ownProps) => ({
	data: Selectors[`${ ownProps.entity }Get`](state),
});

export default connect(mapStateToProps)(SearchBar);
