import PropTypes from 'prop-types';
import React from 'react';
import classnames from 'classnames';
import { ledetekst } from '../diverse/Ledetekst';
import { Spinner } from '../pynt/Spinner';
import { Felt } from './Felt';

const LASTEFORSINKELSE = 200;
const MIMIMUM_ANTALL_SOKETEGN = 3;
const SKJULEFORSINKELSE = 200;

class Sokefelt extends Felt {
	constructor(props) {
		super(props);
		this.state = {};
		this._maks = this.props.maks || 10;
		this._lastetilstand = false;
		this._lastebryter = 0;
		this._registrer('');
		this._obligatorisk = this._sjekk(true).length > 0;
		this._registrer(this.props.verdi());
	}

	_konverter(treff) {
		return this.props.konverter ? treff.map(this.props.konverter) : treff;
	}

	_mottaSok(sok) {
		this.setState({ kandidat: null, sok: sok });
		if (sok === null) {
			return this._mottaVerdi();
		}
		if (sok && String(sok).length < MIMIMUM_ANTALL_SOKETEGN) {
			this.setState({ treff: [] });
			return;
		}
		this.props
			.vedSok(String(sok || '').trim())
			.then((treff) => {
				if (!this.props.konverterTreff) {
					this.setState({
						treff:
							treff instanceof Array
								? treff.slice(0, this._maks)
								: treff,
					});
					return;
				}

				this.setState({
					treff:
						treff instanceof Array
							? this._konverter(treff.slice(0, this._maks))
							: treff,
				});
			})
			.catch(() => this.setState({}));
	}

	_mottaVerdi(verdi) {
		this.setState({ sok: null, treff: null });
		this._registrer(verdi);
		if (this._sjekk(true).length > 0) {
			return;
		}
		this.props.vedVerdi(verdi);
	}

	_mottaTasting(event) {
		var lengde = (this.state.treff || []).length;
		var kandidat = this.state.kandidat || 0;
		switch (event.keyCode) {
			case 9:
				if (lengde > 0) {
					this._mottaVerdi(
						this.state.treff[Math.max(0, kandidat - 1)]
					);
				}
				return;
			case 13:
				if (lengde > 0) {
					this._mottaVerdi(
						this.state.treff[Math.max(0, kandidat - 1)]
					);
				}
				break;
			case 38:
				// gir siste kandidat hvis vi har bladd til 0
				const nyKandidat = (kandidat + lengde) % (lengde + 1) || lengde;
				this._mottaKandidat(nyKandidat);
				break;
			case 40:
				// gir første kandidat hvis vi har bladd rundt
				this._mottaKandidat(Math.max((kandidat + 1) % (lengde + 1), 1));
				break;
			default:
				return;
		}
		event.preventDefault();
		event.stopPropagation();
	}

	_mottaKandidat(kandidat) {
		this.setState({ kandidat: kandidat });
	}

	render() {
		const treff = this.state.treff || [];

		// Vi viser tomme treff kun hvis det foretatt et sok, som er når vi har
		// en søketekst og treff er en array
		const skalViseTreff =
			this.state.fokus &&
			this.state.treff instanceof Array &&
			this.state.sok &&
			MIMIMUM_ANTALL_SOKETEGN <= String(this.state.sok).length;

		// Hvis vi allerede har konvertert treffene kan vi ikke konvertere på nytt
		const alternativer = this.props.konverterTreff
			? treff
			: this._konverter(treff.slice(0, this._maks));
		const formaterHtml = this.props.formaterHtml || false;

		if (typeof this.props.laster === 'function') {
			var laster = this.props.laster();
			if (this.props.laster() != this.lastetilstand) {
				clearTimeout(this.lastebryter);
				this.lastetilstand = laster;
				this.lastebryter = setTimeout(
					() => this.setState({ laster: laster }),
					LASTEFORSINKELSE
				);
			}
		}
		var feilaktig = this._sjekk().length > 0;
		const klasser = classnames(
			'tekstfelt',
			'js-skal-valideres',
			this.props.klasse,
			{
				'har-valideringsfeil': feilaktig,
			}
		);

		return (
			<div
				onKeyDown={(event) => this._mottaTasting(event)}
				onBlur={() =>
					setTimeout(
						() => this.setState({ fokus: false }),
						SKJULEFORSINKELSE
					)
				}
				onFocus={() => this.setState({ fokus: true })}
				className="skjemagruppe sokefelt sokefelt-med-label sokefelt-lys-bakgrunn sokefelt-ekstra-stor"
			>
				{(this.props.tittel || this.props.plassholder) && (
					<label
						className="label-blokk"
						htmlFor={this.id}
						style={{
							display: !this.props.tittel && 'none',
						}}
					>
						{this.props.tittel || this.props.plassholder}
					</label>
				)}
				<div className="util-naboblokker">
					<div className="sokefelt-wrapper">
						<input
							id={this.id}
							aria-invalid={feilaktig}
							aria-describedby={this.id + 'info'}
							type="text"
							autoComplete="off"
							className={klasser}
							onBlur={() => this._vedDimming()}
							onChange={(event) =>
								this._mottaSok(event.target.value)
							}
							placeholder={this.props.plassholder}
							value={
								this.state.sok != null
									? this.state.sok
									: this.props.verdi()
							}
							{...(!!this.props.skalMaskeres
								? { 'data-hj-suppress': true }
								: {})}
						/>
						<input
							type="submit"
							value={ledetekst.getTekst(
								'arbeidsvarsling.frontendkomponenter.Sokefelt.sok'
							)}
							disabled
						/>
					</div>
				</div>
				<div
					aria-busy={!!this.state.laster}
					className="sokeforslag"
					style={{
						display:
							this.state.fokus && skalViseTreff ? null : 'none',
					}}
					{...(!!this.props.skalMaskeres
						? { 'data-hj-suppress': true }
						: {})}
				>
					<Spinner
						className="util-avstand-topp-lite"
						aktivert={!!this.state.laster}
						tekst={ledetekst.getTekst(
							'arbeidsvarsling.frontendkomponenter.Sokefelt.laster'
						)}
					/>
					{!this.state.laster && skalViseTreff && (
						<ul className="liste-ustilet">
							{alternativer.map((alternativ, i) => {
								return (
									<li
										className={
											'valg' +
											(i + 1 === this.state.kandidat
												? ' aktiv'
												: '')
										}
										key={this.id + i}
										onClick={() => {
											if (!this.props.konverterTreff) {
												this._mottaVerdi(
													this.state.treff[i]
												);
												return;
											}
											this._mottaVerdi(alternativ);
										}}
										onMouseEnter={() =>
											this._mottaKandidat(i + 1)
										}
									>
										{formaterHtml ? (
											<div
												dangerouslySetInnerHTML={{
													__html: alternativ,
												}}
											></div>
										) : (
											(
												alternativ || {
													toString: () => '',
												}
											).toString()
										)}
									</li>
								);
							})}
							{alternativer.length === 0 ? (
								<li>
									{ledetekst.getTekst(
										'arbeidsvarsling.frontendkomponenter.Sokefelt.ingentreff'
									)}
								</li>
							) : null}
						</ul>
					)}
				</div>
				{this._renderIrettesettelse()}
			</div>
		);
	}
}

Sokefelt.propTypes = {
	tittel: PropTypes.string,
	laster: PropTypes.func,
	konverter: PropTypes.func,
	konverterTreff: PropTypes.bool,
	plassholder: PropTypes.string,
	verdi: PropTypes.func.isRequired,
	vedSok: PropTypes.func.isRequired,
	vedVerdi: PropTypes.func.isRequired,
	skalMaskeres: PropTypes.bool,
	konverterHtml: PropTypes.bool,
};

export { Sokefelt };
