import {
  make_one_checkbox
} from "./chunk-SA7APTJR.js";
import "./chunk-HJ6L54YS.js";
import {
  HandlerBase
} from "./chunk-LSEFWW72.js";
import "./chunk-SKREEF3H.js";
import "./chunk-HYOEWQ5P.js";
import "./chunk-HBW42TDT.js";
import "./chunk-G6O3URDN.js";
import "./chunk-FN5XPUPH.js";
import "./chunk-IIT367QZ.js";
import "./chunk-RZGEKL77.js";
import "./chunk-UI7OCM2A.js";
import "./chunk-YZK37YCC.js";
import "./chunk-7EMWHCVW.js";
import "./chunk-7IYJZZQI.js";
import "./chunk-M3J4MINX.js";
import "./chunk-PF4DSFDR.js";
import {
  get_bin_label,
  get_bin_range_equation
} from "./chunk-QH6W3NVF.js";
import "./chunk-NOEAT6CX.js";
import "./chunk-4UWS5Y3N.js";
import "./chunk-DD4R5P6W.js";
import "./chunk-JNITUVXP.js";
import "./chunk-KSGA62R2.js";
import "./chunk-LOZEKOES.js";
import "./chunk-TOU7EVFQ.js";
import "./chunk-OAWQ6LOO.js";
import "./chunk-TLT4YIG3.js";
import "./chunk-KYBIQBXE.js";
import "./chunk-I6Y4O3RR.js";
import "./chunk-OMR2DT66.js";
import "./chunk-DQC5FFGV.js";
import "./chunk-HFNDKYVF.js";

// termsetting/handlers/NumBinaryEditor.ts
var NumBinaryEditor = class extends HandlerBase {
  constructor(opts, handler) {
    super(opts);
    this.dom = {};
    this.cutoffPercentile = 50;
    this.opts = opts;
    this.handler = handler;
    this.tw = handler.tw;
    this.q = this.getDefaultQ();
  }
  async showEditMenu(div) {
    this.tw = this.handler.tw;
    this.q = this.getDefaultQ();
    if (this.dom.density_div) {
      if (this.handler.dom.editDiv?.node().contains(this.dom.density_div.node())) {
        await this.handler.density.showViolin(this.dom.density_div, this.getBoundaryOpts());
        return;
      } else {
        this.dom.density_div.remove();
        delete this.dom.density_div;
      }
    }
    this.dom.density_div = div.append("div");
    await this.handler.density.showViolin(this.dom.density_div);
    await this.handler.density.setBinLines(this.getBoundaryOpts());
    this.dom.boundaryInclusionDiv = div.append("div").style("padding", "5px");
    this.dom.cutoff_div = div.append("div").style("padding", "10px");
    this.dom.inputsDiv = div.append("div").style("padding", "10px").style("display", "flex").style("width", "100%");
    this.renderBoundaryInclusionSelect();
    this.renderCutoffInput();
    this.renderBoundaryInputDivs();
  }
  getDefaultQ() {
    const tw = this.termsetting.tw;
    if (tw.q.mode == "binary") {
      const copy = JSON.parse(JSON.stringify(tw.q));
      copy.lst.forEach((bin) => {
        if (!bin.label) bin.label = get_bin_label(bin, tw.q, tw.term.valueConversion);
        bin.range = get_bin_range_equation(bin, this.tw.q);
      });
      return copy;
    }
    const { min, max } = this.handler.density_data;
    const defaultCustomBoundary = (
      /* when no sample is annotated by this term,
      minvalue and maxvalue are both null
      setting defaultCustomBoundary to arbitrary "0" will allow existing UI to work
      but remains to be evaluated if is really okay to use 0
      */
      !Number.isFinite(min) || !Number.isFinite(max) ? 0 : (
        // minvalue and maxvalue is valid number
        max != min ? min + (max - min) / 2 : max
      )
    );
    const firstBin = {
      startunbounded: true,
      startinclusive: false,
      stopinclusive: false,
      stop: +defaultCustomBoundary.toFixed(this.tw.term.type == "integer" ? 0 : 2)
    };
    const lastBin = {
      stopunbounded: true,
      startinclusive: true,
      stopinclusive: false,
      start: +defaultCustomBoundary.toFixed(this.tw.term.type == "integer" ? 0 : 2)
    };
    return {
      mode: "binary",
      type: "custom-bin",
      lst: [
        {
          ...firstBin,
          label: get_bin_label(firstBin, this.tw.q, this.tw.term.valueConversion),
          range: get_bin_range_equation(firstBin, this.tw.q)
        },
        {
          ...lastBin,
          label: get_bin_label(lastBin, this.tw.q, this.tw.term.valueConversion),
          range: get_bin_range_equation(lastBin, this.tw.q)
        }
        //satisfies StopUnboundedBin
      ],
      cutoffType: "normal"
    };
  }
  getBoundaryOpts() {
    return {
      values: [
        {
          //this.q.lst[0].map(bin => ({ x: bin.startunbounded ? bin.stop : bin.start, isDraggable: true })),
          x: this.q.lst[0].stop,
          isDraggable: true
        }
      ],
      callback: (d, value) => {
        this.q.lst[0].stop = value;
        this.q.lst[1].start = value;
        this.dom.cutoffInput.property("value", value);
        this.q.lst = this.processBinaryBinInputs();
        this.dom.customBinRanges.data(this.q.lst).html((d2) => d2.range);
        this.dom.customBinLabelInput.data(this.q.lst).property("value", (d2) => d2.label);
      }
    };
  }
  getBoundaryInclusion() {
    return this.q.lst[0].startinclusive ? "startinclusive" : "stopinclusive";
  }
  renderBoundaryInclusionSelect() {
    this.dom.boundaryInclusionDiv.selectAll("*").remove();
    this.dom.boundaryInclusionDiv.append("span").style("padding", "5px").style("color", "rgb(136, 136, 136)").html("Boundary Inclusion");
    const x = '<span style="font-family:Times;font-style:italic">x</span>';
    this.dom.boundaryInclusionSelect = this.dom.boundaryInclusionDiv.append("select").style("margin-left", "10px").on("change", () => {
      this.renderBoundaryInputDivs();
    });
    this.dom.boundaryInclusionSelect.selectAll("option").data([
      { value: "stopinclusive", html: `start &lt; ${x} &le; end` },
      { value: "startinclusive", html: `start &le; ${x} &lt; end` }
    ]).enter().append("option").property("value", (d) => d.value).property("selected", (d) => this.tw.q.lst?.[0]?.[d.value] == true).html((d) => d.html);
  }
  async renderCutoffInput() {
    this.dom.cutoff_div.append("span").style("margin-right", "5px").style("opacity", 0.5).text("Boundary value");
    const q = this.q;
    this.dom.cutoffInput = this.dom.cutoff_div.append("input").style("width", "100px").attr("type", "number").style("margin-right", "10px").attr("value", q.lst[0].stop).on("change", () => this.renderBoundaryInputDivs());
    this.dom.cutoffPercentileCheckbox = make_one_checkbox({
      holder: this.dom.cutoff_div,
      labeltext: "Use percentile",
      checked: false,
      divstyle: { display: "inline-block" },
      callback: async (checked) => {
        this.dom.cutoffInput.property("disabled", checked == true);
        this.dom.cutoffInputPercentile.style("display", checked ? "" : "none");
        this.handlePercentileChange();
      }
    });
    this.dom.cutoffInputPercentile = this.dom.cutoff_div.append("input").attr("type", "number").attr("value", this.cutoffPercentile).style("display", "none").style("width", "100px").style("margin-right", "10px").on("change", () => this.handlePercentileChange());
  }
  async handlePercentileChange() {
    try {
      const cutoffPercentile = Number(this.dom.cutoffInputPercentile.property("value"));
      this.q.cutoffPercentile = cutoffPercentile;
      const data = await this.termsetting.vocabApi.getPercentile(
        this.tw.term,
        [cutoffPercentile],
        this.termsetting.vocabApi.state?.termfilter
      );
      this.dom.cutoffInput.property("value", data.values[0]);
      this.renderBoundaryInputDivs();
    } catch (e) {
      console.error(e);
    }
  }
  renderBoundaryInputDivs() {
    const cutoff = this.dom.cutoffInput.property("value");
    this.q.lst[0].stop = cutoff;
    this.q.lst[1].start = cutoff;
    this.q.lst = this.processBinaryBinInputs();
    const data = this.q.lst;
    const holder = this.dom.inputsDiv;
    holder.selectAll("*").remove();
    const grid = holder.append("div").style("display", "grid").style("grid-template-columns", "auto auto").style("column-gap", "20px").style("align-items", "center");
    grid.append("div").style("margin-bottom", "3px").style("color", "rgb(136, 136, 136)").text("Range");
    grid.append("div").style("margin-bottom", "3px").style("color", "rgb(136, 136, 136)").text("Bin label");
    for (const d of data) {
      grid.append("div").datum(d).attr("name", "range").html(d.range);
      grid.append("div").append("input").datum(d).attr("type", "text").style("margin", "2px 0px").property("value", d.label).on("change", function() {
        d.label = this.value;
      });
    }
    this.dom.customBinRanges = this.dom.inputsDiv.selectAll('div[name="range"]');
    this.dom.customBinLabelInput = this.dom.inputsDiv.selectAll("input");
    this.handler.density.setBinLines(this.getBoundaryOpts());
  }
  processBinaryBinInputs() {
    const inclusive = this.dom.boundaryInclusionSelect.property("value");
    const startinclusive = inclusive == "startinclusive";
    const stopinclusive = inclusive == "stopinclusive";
    const val = this.q.lst[0].stop;
    if (!val && val !== 0) throw "val is undefined";
    const firstBin = {
      startunbounded: true,
      stop: Number(val),
      startinclusive: false,
      stopinclusive
    };
    const lastBin = {
      start: Number(val),
      startinclusive,
      stopinclusive: false,
      stopunbounded: true
    };
    const bins = [
      {
        ...firstBin,
        label: get_bin_label(firstBin, this.q),
        range: get_bin_range_equation(firstBin, this.tw.q)
      },
      {
        ...lastBin,
        label: get_bin_label(lastBin, this.q),
        range: get_bin_range_equation(lastBin, this.tw.q)
      }
    ];
    return bins;
  }
  getEditedQ(destroyDom = true) {
    const lst = this.processBinaryBinInputs();
    if (destroyDom) {
      for (const name of Object.keys(this.dom)) {
        this.dom[name].remove();
        delete this.dom[name];
      }
    }
    return {
      mode: "binary",
      type: "custom-bin",
      lst
    };
  }
  async undoEdits() {
    this.q = this.getDefaultQ();
    await this.handler.density.setBinLines(this.getBoundaryOpts());
    this.dom.inputsDiv.selectAll("*").remove();
    this.renderBoundaryInclusionSelect();
    this.renderCutoffInput();
    this.renderBoundaryInputDivs();
  }
};
export {
  NumBinaryEditor
};
//# sourceMappingURL=NumBinaryEditor-WMSF7HIO.js.map
