/*
 * Copyright (c) 2015-2018, IGN France.
 * Copyright (c) 2018-2026, Giro3D team.
 * SPDX-License-Identifier: MIT
 */

import type GUI from 'lil-gui';

import { Color } from 'three';

import type Instance from '../core/Instance';
import type Shape from '../entities/Shape';
import type { SegmentLabelFormatter } from '../entities/Shape';

import Coordinates from '../core/geographic/Coordinates';
import CoordinateSystem from '../core/geographic/CoordinateSystem';
import { DEFAULT_COLOR, type VertexLabelFormatter } from '../entities/Shape';
import { DrawTool } from '../interactions/DrawTool';
import Panel from './Panel';

const vertexLabelFormatter: (instance: Instance) => VertexLabelFormatter =
    (instance: Instance) =>
    ({ position }) => {
        const latlon = new Coordinates(instance.coordinateSystem, position.x, position.y).as(
            CoordinateSystem.epsg4326,
        );

        return `lat: ${latlon.latitude.toFixed(5)}°, lon: ${latlon.longitude.toFixed(5)}°`;
    };

const segmentLabelFormatter: SegmentLabelFormatter = params => {
    const length = params.length;
    if (length < 10) {
        return length.toFixed(2);
    }
    return length.toFixed(1);
};

export default class DrawToolPanel extends Panel {
    private readonly _shapes: Shape[] = [];
    private _drawTool?: DrawTool;

    public color: Color = new Color(DEFAULT_COLOR);

    public get pendingColor(): Color {
        return new Color(this.color).offsetHSL(0, 0, -0.1);
    }

    public constructor(parent: GUI, instance: Instance) {
        super(parent, instance, 'DrawTool');

        this.addColorController(this, 'color').onChange(c =>
            this._shapes.forEach(shape => (shape.color = c)),
        );
        this.addController(this, 'createSegment').name('Segment');
        this.addController(this, 'createPolygon').name('Polygon');
        this.addController(this, 'createPoint').name('Point');
        this.addController(this, 'clear').name('Clear');
    }

    private onShapeFinished(shape: Shape | null): void {
        if (shape != null) {
            shape.color = this.color;
            this._shapes.push(shape);
        }
    }

    private createDrawToolIfNecessary(): DrawTool {
        if (!this._drawTool) {
            this._drawTool = new DrawTool({
                instance: this.instance,
                domElement: this.instance.domElement,
            });
        }

        return this._drawTool;
    }

    public createSegment(): void {
        const tool = this.createDrawToolIfNecessary();

        tool.createSegment({
            showSegmentLabels: true,
            segmentLabelFormatter,
            color: this.pendingColor,
        }).then(shape => this.onShapeFinished(shape));
    }

    public createPoint(): void {
        const tool = this.createDrawToolIfNecessary();

        tool.createPoint({
            vertexLabelFormatter: vertexLabelFormatter(this.instance),
            showVertexLabels: true,
            color: this.pendingColor,
        }).then(shape => this.onShapeFinished(shape));
    }

    public createPolygon(): void {
        const tool = this.createDrawToolIfNecessary();

        tool.createPolygon({
            showSurfaceLabel: true,
            color: this.pendingColor,
        }).then(shape => this.onShapeFinished(shape));
    }

    public clear(): void {
        this._shapes.forEach(shape => this.instance.remove(shape));
        this._shapes.length = 0;
    }
}
