import classNames from 'classnames'
import { T } from 'Components'
import InputSuggestions from 'Components/conversation/InputSuggestions'
import PercentageField from 'Components/PercentageField'
import PeriodSwitch from 'Components/PeriodSwitch'
import withColours from 'Components/utils/withColours'
import withLanguage from 'Components/utils/withLanguage'
import withSitePaths from 'Components/utils/withSitePaths'
import { encodeRuleName } from 'Engine/rules'
import { compose, isEmpty, isNil, propEq } from 'ramda'
import React, { Component, PureComponent } from 'react'
import emoji from 'react-easy-emoji'
import { withTranslation } from 'react-i18next'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { change, Field, formValueSelector, reduxForm } from 'redux-form'
import {
	analysisWithDefaultsSelector,
	flatRulesSelector
} from 'Selectors/analyseSelectors'
import Animate from 'Ui/animate'
import AnimatedTargetValue from 'Ui/AnimatedTargetValue'
import CurrencyInput from './CurrencyInput/CurrencyInput'
import './TargetSelection.css'
import { serialiseUnit } from 'Engine/units'

export default compose(
	withTranslation(),
	withColours,
	reduxForm({
		form: 'conversation',
		destroyOnUnmount: false
	}),
	connect(
		state => ({
			getTargetValue: dottedName =>
				formValueSelector('conversation')(state, dottedName),
			analysis: analysisWithDefaultsSelector(state),
			flatRules: flatRulesSelector(state),
			activeInput: state.activeTargetInput,
			objectifs: state.simulation?.config.objectifs || [],
			secondaryObjectives:
				state.simulation?.config['objectifs secondaires'] || []
		}),
		dispatch => ({
			setFormValue: (field, name) =>
				dispatch(change('conversation', field, name)),
			setActiveInput: name =>
				dispatch({ type: 'SET_ACTIVE_TARGET_INPUT', name })
		})
	)
)(
	class TargetSelection extends PureComponent {
		state = {
			initialRender: true
		}
		getTargets() {
			let { secondaryObjectives, analysis } = this.props
			if (!analysis) return []
			return analysis.targets.filter(
				t => !secondaryObjectives.includes(t.dottedName)
			)
		}
		componentDidMount() {
			const props = this.props
			let targets = this.getTargets()
			// Initialize defaultValue for target that can't be computed
			targets
				.filter(
					target =>
						(!target.formule || isEmpty(target.formule)) &&
						(!isNil(target.defaultValue) ||
							!isNil(target.explanation?.defaultValue)) &&
						!props.getTargetValue(target.dottedName)
				)

				.forEach(target => {
					props.setFormValue(
						target.dottedName,
						!isNil(target.defaultValue)
							? target.defaultValue
							: target.explanation?.defaultValue
					)
				})

			if (this.state.initialRender) {
				this.setState({ initialRender: false })
			}
		}
		render() {
			let {
					colours,
					activeInput,
					setActiveInput,
					setFormValue,
					objectifs
				} = this.props,
				targets = this.getTargets()

			return (
				<div id="targetSelection">
					{(typeof objectifs[0] === 'string' ? [{ objectifs }] : objectifs).map(
						({ icône, objectifs: groupTargets, nom }, index) => (
							<React.Fragment key={nom || '0'}>
								<div style={{ display: 'flex', alignItems: 'end' }}>
									<div style={{ flex: 1 }}>
										{nom && (
											<h2 style={{ marginBottom: 0 }}>
												{emoji(icône)} <T>{nom}</T>
											</h2>
										)}
									</div>
									{index === 0 && <PeriodSwitch />}
								</div>
								<section
									className="ui__ plain card"
									style={{
										marginTop: '.6em',
										color: colours.textColour,
										background: `linear-gradient(
								60deg,
								${colours.darkColour} 0%,
								${colours.colour} 100%
								)`
									}}>
									<Targets
										{...{
											activeInput,
											setActiveInput,
											setFormValue,
											targets: targets.filter(({ dottedName }) =>
												groupTargets.includes(dottedName)
											),
											initialRender: this.state.initialRender
										}}
									/>
								</section>
							</React.Fragment>
						)
					)}
				</div>
			)
		}
	}
)

let Targets = ({
	activeInput,
	setActiveInput,
	setFormValue,
	targets,
	initialRender
}) => (
	<div>
		<ul className="targets">
			{targets
				.map(target => target.explanation || target)
				.filter(target => {
					return (
						target.isApplicable !== false &&
						(target.question || target.nodeValue)
					)
				})
				.map(target => (
					<Target
						key={target.dottedName}
						initialRender={initialRender}
						{...{
							target,
							setFormValue,
							activeInput,
							setActiveInput,
							targets
						}}
					/>
				))}
		</ul>
	</div>
)

const Target = ({
	target,
	activeInput,

	targets,
	setActiveInput,
	setFormValue,
	initialRender
}) => {
	const isSmallTarget =
		!target.question || !target.formule || isEmpty(target.formule)

	return (
		<li
			key={target.name}
			className={isSmallTarget ? 'small-target' : undefined}>
			<Animate.appear unless={initialRender}>
				<div>
					<div className="main">
						<Header
							{...{
								target,

								isActiveInput: activeInput === target.dottedName
							}}
						/>
						{isSmallTarget && (
							<span
								style={{
									flex: 1,
									borderBottom: '1px dashed #ffffff91',
									marginLeft: '1rem'
								}}
							/>
						)}
						<TargetInputOrValue
							{...{
								target,
								targets,
								activeInput,
								setActiveInput,
								setFormValue
							}}
						/>
					</div>
					{activeInput === target.dottedName && (
						<Animate.fromTop>
							<InputSuggestions
								suggestions={target.suggestions}
								onFirstClick={value => {
									setFormValue(target.dottedName, '' + value)
								}}
								rulePeriod={target.période}
								colouredBackground={true}
							/>
						</Animate.fromTop>
					)}
				</div>
			</Animate.appear>
		</li>
	)
}

let Header = withSitePaths(({ target, sitePaths }) => {
	const ruleLink =
		sitePaths.documentation.index + '/' + encodeRuleName(target.dottedName)
	return (
		<span className="header">
			<span className="texts">
				<span className="optionTitle">
					<Link to={ruleLink}>{target.title || target.name}</Link>
				</span>
				<p>{target.summary}</p>
			</span>
		</span>
	)
})

let CurrencyField = withColours(props => {
	return (
		<CurrencyInput
			style={{
				color: props.colours.textColour,
				borderColor: props.colours.textColour
			}}
			debounce={600}
			className="targetInput"
			value={props.input.value}
			{...props.input}
			{...props}
		/>
	)
})
let DebouncedPercentageField = props => (
	<PercentageField debounce={600} {...props} />
)

let TargetInputOrValue = withLanguage(
	({
		target,
		targets,
		activeInput,
		setActiveInput,
		language,
		firstStepCompleted
	}) => {
		let inputIsActive = activeInput === target.dottedName
		return (
			<span className="targetInputOrValue">
				{inputIsActive || !target.formule || isEmpty(target.formule) ? (
					<Field
						name={target.dottedName}
						onBlur={event => event.preventDefault()}
						component={
							{ '€': CurrencyField, '%': DebouncedPercentageField }[
								serialiseUnit(target.unit)
							]
						}
						{...(inputIsActive ? { autoFocus: true } : {})}
						language={language}
					/>
				) : (
					<TargetValue
						{...{
							targets,
							target,
							activeInput,
							setActiveInput,
							firstStepCompleted
						}}
					/>
				)}
			</span>
		)
	}
)

const TargetValue = connect(
	state => ({
		blurValue: analysisWithDefaultsSelector(state)?.cache.inversionFail
	}),
	dispatch => ({
		setFormValue: (field, name) => dispatch(change('conversation', field, name))
	})
)(
	class TargetValue extends Component {
		render() {
			let { targets, target, blurValue } = this.props

			let targetWithValue =
					targets && targets.find(propEq('dottedName', target.dottedName)),
				value = targetWithValue && targetWithValue.nodeValue

			return (
				<div
					className={classNames({
						editable: target.question,
						attractClick: target.question && isNil(target.nodeValue)
					})}
					style={blurValue ? { filter: 'blur(3px)' } : {}}
					{...(target.question ? { tabIndex: 0 } : {})}
					onClick={this.showField(value)}
					onFocus={this.showField(value)}>
					<AnimatedTargetValue value={value} />
				</div>
			)
		}
		showField(value) {
			let { target, setFormValue, activeInput, setActiveInput } = this.props
			return () => {
				if (!target.question) return
				if (value != null && !Number.isNaN(value))
					setFormValue(target.dottedName, Math.round(value) + '')

				if (activeInput) setFormValue(activeInput, '')
				setActiveInput(target.dottedName)
			}
		}
	}
)