/*
    ***** BEGIN LICENSE BLOCK *****
    
    Copyright © 2019 Corporation for Digital Scholarship
                     Vienna, Virginia, USA
                     https://digitalscholar.org
    
    This file is part of Zotero.
    
    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.
    
    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.
    
    ***** END LICENSE BLOCK *****
*/

'use strict';

const React = require('react');
const PropTypes = require('prop-types');
const { pick } = require('./utils');

class Search extends React.PureComponent {
	constructor(props) {
		super(props);
		this.inputRef = React.createRef();
	}
	
	state = {
		immediateValue: this.props.value
	};
	
	static getDerivedStateFromProps(props, state) {
		var prevProps = state.prevProps || {};
		return {
			prevProps: props,
			immediateValue: prevProps.value !== props.value
				? props.value
				: state.immediateValue
		};
	}
	
	handleChange = (event) => {
		var value = event.target.value;
		// Update controlled value and cancel button immediately
		this.setState({
			immediateValue: value
		});
		// Debounce the search based on the timeout
		if (this._timeout) {
			clearTimeout(this._timeout);
		}
		this._timeout = this.props.timeout
			&& setTimeout(() => this.props.onSearch(value), this.props.timeout);
	}
	
	handleClear = () => {
		if (this._timeout) {
			clearTimeout(this._timeout);
		}
		this.setState({
			immediateValue: ''
		});
		this.props.onSearch('');
	}
	
	handleKeyDown = (event) => {
		if (event.key == 'Escape') {
			this.handleClear();
		}
	}
	
	focus() {
		this.inputRef.current.focus();
	}
	
	render() {
		return (
			<div className="search">
				<input
					ref={this.inputRef}
					type="search"
					onChange={this.handleChange}
					onKeyDown={this.handleKeyDown}
					value={this.state.immediateValue}
					className="search-input"
					{...pick(this.props, p => p.startsWith('data-') || p.startsWith('aria-'))}
				/>
				{this.state.immediateValue !== ''
					? <div
						className="search-cancel-button"
						onClick={this.handleClear}/>
					: ''}
			</div>
		);
	}

	static propTypes = {
		inputRef: PropTypes.object,
		onSearch: PropTypes.func,
		timeout: PropTypes.number,
		value: PropTypes.string,
		placeholder: PropTypes.string,
	};

	static defaultProps = {
		onSearch: () => {},
		timeout: 300,
		value: '',
	};
}

module.exports = Search;
