import Engine from 'Engine'
import { formatValue } from 'Engine/format'
import { EvaluatedNode } from 'Engine/types'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { DottedName } from 'Rules'
import { coerceArray } from '../utils'
import RuleLink from './RuleLink'
import { EngineContext } from './utils/EngineContext'

export type ValueProps = {
	expression: string
	unit?: string
	displayedUnit?: string
	precision?: number
	engine?: Engine<DottedName>
	linkToRule?: boolean
} & React.HTMLProps<HTMLSpanElement>

export default function Value({
	expression,
	unit,
	displayedUnit,
	precision,
	engine,
	linkToRule = true,
	...props
}: ValueProps) {
	const { language } = useTranslation().i18n
	if (expression === null) {
		throw new TypeError('expression cannot be null')
	}
	const evaluation = (engine ?? useContext(EngineContext)).evaluate(
		expression,
		{ unit }
	)
	const nodeValue = evaluation.nodeValue
	const value = formatValue({
		nodeValue,
		unit:
			displayedUnit ?? (evaluation as EvaluatedNode<DottedName, number>).unit,
		language,
		precision
	})
	if ('dottedName' in evaluation && linkToRule) {
		return (
			<RuleLink {...evaluation}>
				<span {...props}>{value}</span>
			</RuleLink>
		)
	}
	return <span {...props}>{value}</span>
}

type ConditionProps = {
	expression: string | string[]
	children: React.ReactNode
}
export function Condition({ expression, children }: ConditionProps) {
	const engine = useContext(EngineContext)
	if (!coerceArray(expression).every(expr => engine.evaluate(expr).nodeValue)) {
		return null
	}
	return <>{children}</>
}
