import type { ValidationState } from '../../common/static-wrappers/interfaces/validation-interface';
import { Component, Prop, toNative } from 'vue-facing-decorator';
import PowerduckState from '../../app/powerduck-state';
import TsxComponent from '../../app/vuetsx';
import BoundingBox from '../../data/bounding-box';
import FlexContainer from '../form/flex-container';
import FlexFormItem from '../form/form-item-flex';
import FormItemWrapper from '../form/form-item-wrapper';
import OpenStreetMap from '../open-street-map/open-street-map';
import NumericInput, { NumericInputMode } from './numeric-input';

interface GpsBoundingBoxInputArgs {
	bBoxModel: BoundingBox;
	mandatory?: boolean;
	disabled?: boolean;
	/**
	 * QA_AT-8: optional callback fired after every operator edit to a bbox
	 * field. Lets the consumer (e.g. Resort modal) flip a
	 * `hasOperatorEditedBbox` flag so subsequent country / GPS changes stop
	 * auto-recomputing the bbox. Backward-compatible: existing call sites that
	 * omit it see no behaviour change.
	 */
	changed?: (field: keyof BoundingBox, value: number) => void;
}

@Component
class GpsBoundingBoxInputComponent extends TsxComponent<GpsBoundingBoxInputArgs> implements GpsBoundingBoxInputArgs {
	@Prop() bBoxModel: BoundingBox;
	@Prop() mandatory?: boolean;
	@Prop() disabled?: boolean;
	@Prop() changed?: (field: keyof BoundingBox, value: number) => void;

	onChange(field: keyof BoundingBox, value: number) {
		// QA_AT-11: align with `GpsInput` and round to 6 decimals (~11 cm) via
		// the shared `BoundingBox.roundCoord` (same rule as the server's
		// GpsHelper.roundCoord). QA_AT-24: NumericInput string-truncates while
		// typing (via maxDecimals={6} in renderInput); this round remains as a
		// defence-in-depth net for non-input paths — paste, programmatic bbox
		// prefills from country / GPS centroid recompute, etc.
		this.bBoxModel[field] = BoundingBox.roundCoord(value);

		if (this.changed) {
			this.changed(field, this.bBoxModel[field]);
		}
	}

	renderInput(
		h: any,
		label: string,
		value: number,
		onChanged?: (value: number) => void,
		showClearValueButton?: boolean,
		validationState?: ValidationState,
	) {
		return (
			<FlexFormItem flexFill={true}>
				<NumericInput
					mandatory={this.mandatory}
					label={label}
					value={value}
					step={0.000001}
					maxDecimals={6}
					mode={NumericInputMode.Clasic}
					showClearValueButton={showClearValueButton}
					validationState={validationState}
					disabled={this.disabled}
					changed={(e) => {
						if (onChanged != null) {
							onChanged(e);
						}
					}}
				/>
			</FlexFormItem>
		);
	}

	render(h) {
		if (!this.bBoxModel) {
			return null;
		}

		// QA_AT-8: column order is latitudes (Y) on the left, longitudes (X) on
		// the right, matching `gps-input.tsx` lat-left / long-right semantics.
		return (
			<div>
				<FormItemWrapper label={PowerduckState.getResourceValue('gpsBoundingBoxLabel')} mandatory={this.mandatory}>
					<FlexContainer fullWidthOnMobile={true}>
						<FlexFormItem>
							{this.renderInput(
								h,
								PowerduckState.getResourceValue('gpsBoundingBoxY1'),
								this.bBoxModel.y1,
								e => this.onChange('y1', e),
							)}
							{this.renderInput(
								h,
								PowerduckState.getResourceValue('gpsBoundingBoxY2'),
								this.bBoxModel.y2,
								e => this.onChange('y2', e),
							)}
						</FlexFormItem>
						<FlexFormItem>
							{this.renderInput(
								h,
								PowerduckState.getResourceValue('gpsBoundingBoxX1'),
								this.bBoxModel.x1,
								e => this.onChange('x1', e),
							)}
							{this.renderInput(
								h,
								PowerduckState.getResourceValue('gpsBoundingBoxX2'),
								this.bBoxModel.x2,
								e => this.onChange('x2', e),
							)}
						</FlexFormItem>
					</FlexContainer>
				</FormItemWrapper>

				<FormItemWrapper label={null} mandatory={false}>
					<div class="rounded">
						<OpenStreetMap
							ref="openStreetMap"
							isCenterHidden={true}
							bBox={this.bBoxModel}
						/>
					</div>
				</FormItemWrapper>
			</div>
		);
	}
}

const GpsBoundingBoxInput = toNative(GpsBoundingBoxInputComponent);
export default GpsBoundingBoxInput;
