import { RegionSelectTool, RegionSelectToolView } from "./region_select_tool";
import { PolyAnnotation } from "../../annotations/poly_annotation";
import { tool_icon_polygon_select } from "../../../styles/icons.css";
export class PolySelectToolView extends RegionSelectToolView {
    static __name__ = "PolySelectToolView";
    _is_selecting = false;
    _mappers() {
        const mapper = (units, scale, view, canvas) => {
            switch (units) {
                case "canvas": return canvas;
                case "screen": return view;
                case "data": return scale;
            }
        };
        const { overlay } = this.model;
        const { frame, canvas } = this.plot_view;
        const { x_scale, y_scale } = frame;
        const { x_view, y_view } = frame.bbox;
        const { x_screen, y_screen } = canvas.bbox;
        return {
            x: mapper(overlay.xs_units, x_scale, x_view, x_screen),
            y: mapper(overlay.ys_units, y_scale, y_view, y_screen),
        };
    }
    _v_compute(xs, ys) {
        const { x, y } = this._mappers();
        return [x.v_compute(xs), y.v_compute(ys)];
    }
    _v_invert(sxs, sys) {
        const { x, y } = this._mappers();
        return [x.v_invert(sxs), y.v_invert(sys)];
    }
    connect_signals() {
        super.connect_signals();
        const { pan } = this.model.overlay;
        this.connect(pan, ([phase, ev]) => {
            if ((phase == "pan" && this._is_continuous(ev)) || (phase == "pan:end" && !this._is_selecting)) {
                const { xs, ys } = this.model.overlay;
                const [sxs, sys] = this._v_compute(xs, ys);
                this._do_select(sxs, sys, false, this._select_mode(ev));
            }
        });
        const { active } = this.model.properties;
        this.on_change(active, () => {
            if (!this.model.active && !this.model.persistent) {
                this._clear_overlay();
            }
        });
    }
    _tap(ev) {
        const { sx, sy } = ev;
        const { frame } = this.plot_view;
        if (!frame.bbox.contains(sx, sy)) {
            return;
        }
        this._clear_other_overlays();
        const [sxs, sys] = (() => {
            if (this._is_selecting) {
                const { xs, ys } = this.model.overlay;
                const [sxs, sys] = this._v_compute(xs, ys);
                return [[...sxs], [...sys]];
            }
            else {
                this._is_selecting = true;
                return [[], []];
            }
        })();
        sxs.push(sx);
        sys.push(sy);
        const [xs, ys] = this._v_invert(sxs, sys);
        this.model.overlay.update({ xs, ys });
        if (this._is_continuous(ev.modifiers)) {
            this._do_select(sxs, sys, true, this._select_mode(ev.modifiers));
        }
    }
    _finish_selection(ev) {
        this._is_selecting = false;
        const { xs, ys } = this.model.overlay;
        const [sxs, sys] = this._v_compute(xs, ys);
        this._do_select(sxs, sys, true, this._select_mode(ev));
        this.plot_view.state.push("poly_select", { selection: this.plot_view.get_selection() });
        if (!this.model.persistent) {
            this._clear_overlay();
        }
    }
    _press(ev) {
        this._finish_selection(ev.modifiers);
    }
    _keyup(ev) {
        if (!this.model.active) {
            return;
        }
        if (ev.key == "Enter") {
            this._finish_selection(ev.modifiers);
            return;
        }
        if (ev.key == "Escape") {
            if (this.model.overlay.visible) {
                this._clear_overlay();
                return;
            }
        }
        super._keyup(ev);
    }
    _clear_selection() {
        if (this.model.overlay.visible) {
            this._clear_overlay();
        }
        else {
            this._is_selecting = false;
            super._clear_selection();
        }
    }
    _clear_overlay() {
        this._is_selecting = false;
        super._clear_overlay();
    }
    _do_select(sx, sy, final, mode) {
        const { greedy } = this.model;
        const geometry = { type: "poly", sx, sy, greedy };
        this._select(geometry, final, mode);
    }
}
export const DEFAULT_POLY_OVERLAY = () => {
    return new PolyAnnotation({
        syncable: false,
        level: "overlay",
        visible: false,
        editable: true,
        xs_units: "data",
        ys_units: "data",
        fill_color: "lightgrey",
        fill_alpha: 0.5,
        line_color: "black",
        line_alpha: 1.0,
        line_width: 2,
        line_dash: [4, 4],
    });
};
export class PolySelectTool extends RegionSelectTool {
    static __name__ = "PolySelectTool";
    constructor(attrs) {
        super(attrs);
    }
    static {
        this.prototype.default_view = PolySelectToolView;
        this.define(({ Ref }) => ({
            overlay: [Ref(PolyAnnotation), DEFAULT_POLY_OVERLAY],
        }));
        this.register_alias("poly_select", () => new PolySelectTool());
    }
    tool_name = "Poly Select";
    tool_icon = tool_icon_polygon_select;
    event_type = "tap";
    default_order = 11;
}
//# sourceMappingURL=poly_select_tool.js.map