import PropTypes from 'prop-types';
import React, { Component, useState } from 'react';
import classnames from 'classnames';
import { Felt } from './Felt';
import { guid } from '../diverse/guid';
import { Tekstfelt } from './Tekstfelt';
import { Gyldighet } from './Gyldighet';

class Sjekkboks extends Component {
	constructor(props) {
		super(props);
		this.id = guid();
	}

	render() {
		const id = this.id;

		const klasser = classnames('sjekkboks', this.props.klasse);
		return (
			<>
				<input
					tabIndex={0}
					type="checkbox"
					id={id}
					key={'input_' + id}
					className={klasser}
					onChange={(event) =>
						this.props.vedVerdi(event.target.checked)
					}
					checked={this.props.verdi()}
				/>
				<label htmlFor={id}>{this.props.tittel}</label>
				{this.props.children}
			</>
		);
	}
}

/**
 * Wrapper en div kun hvis vi skal sette className, men wrapper React.Fragment ellers.
 *
 * Dette gjør at vi får ekstra DOM-noder for sjekkboksgruppe kun der det trengs, og ikke
 * en DOM-node der vi ikke trenger det (siden dette ødelegger rendringen i andre tilfeller)
 */
function KanskjeKlasse(props) {
	const { children, ...rest } = props;
	if (props.className) {
		return <div {...rest}>{children}</div>;
	}
	return <React.Fragment>{children}</React.Fragment>;
}

Sjekkboks.propTypes = {
	element: PropTypes.string,
	verdi: PropTypes.func,
	tittel: PropTypes.string,
	vedVerdi: PropTypes.func.isRequired,
};

class Sjekkboksgruppe extends Felt {
	constructor(props) {
		super(props);
		this.state = {
			...(this.state || {}),
			valgte: props.valgte || props.alternativer.map((alt) => false),
		};
		this._registrerSjekkboks();
	}
	_registrerSjekkboks() {
		this._registrer(this.state.valgte.some((v) => !!v) ? 'valgt' : '');
	}
	_vedValg(indeks) {
		if (indeks === undefined) {
			const velges = !this.state.valgte.every((v) => v);
			this.state.valgte = this.state.valgte.map((v) => velges);
		} else {
			this.state.valgte[indeks] = !this.state.valgte[indeks];
		}
		this._registrerSjekkboks();
		if (this._sjekk().length > 0) {
			return;
		}
		this.props.vedValg(this.state.valgte);
	}
	render() {
		const ytreKlasser = classnames('util-leselengde', {
			'liste-kolonner': this.props.kolonner,
			'util-naboblokker': this.props.naboblokker,
		});
		const indreKlasser = classnames('radiosjekk-kolonne', 'skjemagruppe');
		const klasser = classnames(ytreKlasser, indreKlasser);

		return (
			<>
				{this.props.velgAlle && (
					<div className={'radiosjekk-kolonne skjemagruppe'}>
						<Sjekkboks
							tittel={this.props.velgAlle}
							verdi={() => this.state.valgte.every((v) => v)}
							vedVerdi={() => this._vedValg()}
						/>
					</div>
				)}
				<div className={this.props.naboblokker ? ytreKlasser : klasser}>
					{this.props.alternativer.map((alt, i) => (
						<KanskjeKlasse
							className={this.props.naboblokker && indreKlasser}
							key={alt}
						>
							<Sjekkboks
								key={alt}
								tittel={
									typeof this.props.formater === 'function'
										? this.props.formater(alt)
										: alt
								}
								verdi={() => !!this.state.valgte[i]}
								vedVerdi={() => this._vedValg(i)}
							/>
						</KanskjeKlasse>
					))}
				</div>
				{this._renderIrettesettelse()}
			</>
		);
	}
}

function SjekkboksMedTekst(props) {
	const {
		gyldighet,
		tekst,
		etikett,
		valgt,
		oppdaterTekst,
		children,
		tekstTittel,
		plassholder,
		irettesettelse,
		oppdaterValgt,
		makslengde,
		under,
	} = props;
	const [sjekkboksValgt, setSjekkboksValgt] = useState(valgt);

	// Vi har lokal kontroll på valg av sjekkboks for å gi mer snappy gui
	function oppdaterSjekkboks(verdi) {
		setSjekkboksValgt(verdi);
		oppdaterValgt(verdi);
	}

	return (
		<Sjekkboks
			tittel={etikett}
			verdi={() => sjekkboksValgt}
			vedVerdi={oppdaterSjekkboks}
		>
			{sjekkboksValgt && (
				<div className="sjekkboks-med-innhold">
					{children}
					<Tekstfelt
						gyldighet={gyldighet.obligatorisk()}
						irettesettelse={irettesettelse}
						linjer={3}
						klasse="input-mellomstor"
						tittel={tekstTittel}
						verdi={() => tekst}
						plassholder={plassholder}
						vedVerdi={oppdaterTekst}
						maxLength={makslengde}
					/>
					{under}
				</div>
			)}
		</Sjekkboks>
	);
}

SjekkboksMedTekst.propTypes = {
	tekst: PropTypes.string,
	etikett: PropTypes.string,
	valgt: PropTypes.bool,
	oppdaterTekst: PropTypes.func.isRequired,
	gyldighet: PropTypes.instanceOf(Gyldighet).isRequired,
	children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
	tekstTittel: PropTypes.string,
	plassholder: PropTypes.string,
	irettesettelse: PropTypes.string,
	oppdaterValgt: PropTypes.func.isRequired,
	makslengde: PropTypes.number,
	under: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
};

Sjekkboksgruppe.propTypes = {
	alternativer: PropTypes.arrayOf(PropTypes.string).isRequired,
	formater: PropTypes.func,
	kolonner: PropTypes.bool,
	naboblokker: PropTypes.bool,
	valgte: PropTypes.arrayOf(PropTypes.bool),
	vedValg: PropTypes.func.isRequired,
	velgAlle: PropTypes.string,
};

export { Sjekkboks, Sjekkboksgruppe, SjekkboksMedTekst };
