import {
  make_radios
} from "./chunk-SA7APTJR.js";
import {
  initBinConfig
} from "./chunk-7EMWHCVW.js";
import {
  format
} from "./chunk-OAWQ6LOO.js";

// termsetting/handlers/NumRegularBinEditor.ts
var NumRegularBinEditor = class {
  constructor(editHandler) {
    this.dom = {};
    this.editHandler = editHandler;
    this.opts = editHandler.opts;
    this.tw = editHandler.tw;
    this.termsetting = editHandler.termsetting;
  }
  render(div) {
    this.tw = this.editHandler.tw;
    this.q = this.getDefaultQ();
    this.editHandler.handler.density.setBinLines(this.getBoundaryOpts());
    if (this.dom.binsTable) {
      if (this.editHandler.dom.binsDiv?.node().contains(this.dom.binsTable.node())) return;
      else {
        this.dom.binsTable.remove();
        delete this.dom.binsTable;
      }
    }
    const binsTable = div.append("table");
    this.dom.binsTable = binsTable;
    this.renderBinSizeInput(binsTable.append("tr"));
    this.renderFirstBinInput(binsTable.append("tr"));
    this.renderLastBinInputs(binsTable.append("tr"));
  }
  getDefaultQ() {
    if (this.tw.q.type == "regular-bin") return JSON.parse(JSON.stringify(this.tw.q));
    const t = this.tw.term;
    const defaultQ = this.termsetting.opts.use_bins_less && t.bins?.less || t.bins?.default;
    if (defaultQ) return JSON.parse(JSON.stringify(defaultQ));
    const binConfig = initBinConfig(this.editHandler.handler.density_data);
    return typeof binConfig == "string" ? JSON.parse(binConfig) : binConfig;
  }
  renderBinSizeInput(tr) {
    const handler = this.editHandler.handler;
    tr.append("td").style("margin", "5px").style("opacity", 0.5).text("Bin Size");
    const { min, max } = handler.density_data;
    const q = this.q;
    const origBinSize = q.bin_size;
    this.dom.bin_size_input = tr.append("td").append("input").attr("type", "number").attr("value", "rounding" in q ? format(q.rounding || ".0f")(q.bin_size) : q.bin_size).attr("data-testid", "sjpp-num-reg-bin-editor-size").style("margin-left", "15px").style("width", "100px").style("color", () => q.bin_size > Math.abs(max - min) ? "red" : "").on("change", (event) => {
      const newValue = Number(event.target.value);
      if (newValue <= 0) {
        window.alert("Please enter non-negative bin size.");
        event.target.value = origBinSize;
        return;
      }
      if ((max - min) / newValue > 100) {
        window.alert("Bin size too small. Try setting a bigger value.");
        event.target.value = origBinSize;
        return;
      }
      q.bin_size = newValue;
      this.dom.bin_size_input.style("color", q.bin_size > max - min ? "red" : newValue != origBinSize ? "green" : "");
      handler.density.setBinLines(this.getBoundaryOpts());
    });
  }
  renderFirstBinInput(tr) {
    const handler = this.editHandler.handler;
    const q = this.q;
    if (!q.first_bin) throw "missing q.first_bin";
    tr.append("td").style("margin", "5px").style("opacity", 0.5).text("First Bin Stop");
    const { min, max } = handler.density_data;
    const origValue = q.first_bin.stop;
    this.dom.first_stop_input = tr.append("td").append("input").attr("type", "number").property("value", origValue).style("width", "100px").style("margin-left", "15px").on("change", (event) => {
      const newValue = Number(event.target.value);
      if (newValue < min || newValue > max) {
        window.alert("First bin stop value out of bound.");
        event.target.value = origValue;
        return;
      }
      this.q.first_bin.stop = newValue;
      handler.density.setBinLines(this.getBoundaryOpts());
    });
    tr.append("td").append("div").style("font-size", ".6em").style("opacity", 0.5).style("display", handler.density.no_density_data ? "none" : "block").text("Indicated by left-most red line. Drag to change.");
  }
  renderLastBinInputs(tr) {
    const handler = this.editHandler.handler;
    const q = this.q;
    const isAuto = !q.last_bin || !Number.isFinite(q.last_bin.start);
    tr.append("td").style("padding-top", "4px").style("opacity", 0.5).style("vertical-align", "top").text("Last Bin Start");
    const td1 = tr.append("td").style("padding-left", "15px").style("vertical-align", "top");
    const radio_div = td1.append("div");
    const radios = make_radios({
      holder: radio_div,
      options: [
        { label: "Automatic", value: "auto", checked: isAuto },
        { label: "Fixed", value: "fixed", checked: !isAuto }
      ],
      callback: (v) => {
        if (v == "auto") {
          delete q.last_bin;
          edit_div.style("display", "none");
          handler.density.setBinLines(this.getBoundaryOpts());
          return;
        }
        edit_div.style("display", "inline-block");
        if (this.dom.last_start_input.property("value") == "") {
          this.dom.last_start_input.property("value", this.tw.q.last_bin?.start || handler.density_data.max);
        }
        this.setLastBinStart();
      }
    });
    this.dom.fixed_radio = radios.inputs.filter((_, i) => i === 1);
    const edit_div = tr.append("td").append("div").style("display", isAuto ? "none" : "inline-block");
    this.dom.last_start_input = edit_div.append("input").attr("type", "number").property("value", q.last_bin?.start || "").style("width", "100px").on("change", () => this.setLastBinStart());
    edit_div.append("div").style("font-size", ".6em").style("opacity", 0.5).style("display", handler.density.no_density_data ? "none" : "block").text("Indicated by right-most red line. Drag to change.");
  }
  setLastBinStart() {
    const q = this.q;
    const { max } = this.editHandler.handler.density_data;
    const strInput = this.dom.last_start_input.property("value");
    if (strInput === "") return;
    const inputValue = Number(strInput);
    if (q.first_bin && inputValue <= q.first_bin.stop) {
      window.alert("Last bin start cannot be smaller than first bin stop.");
      this.dom.last_start_input.property("value", max);
      return;
    }
    if (inputValue > max) {
      window.alert("Last bin start value out of bound.");
      this.dom.last_start_input.property("value", max);
      return;
    }
    if (q.last_bin) q.last_bin.start = inputValue;
    else
      q.last_bin = {
        start: inputValue,
        stopunbounded: true,
        stopinclusive: false
      };
    this.editHandler.handler.density.setBinLines(this.getBoundaryOpts());
  }
  getBoundaryOpts() {
    const { min, max } = this.editHandler.handler.density_data;
    const binLinesStop = this.q.last_bin?.start ?? max + Math.abs(this.q.first_bin.stop) - Math.min(min, 0);
    const boundaryValues = [];
    for (let i = this.q.first_bin.stop; i <= binLinesStop; i = i + this.q.bin_size) {
      if (this.q.last_bin?.start === i) break;
      if (i > binLinesStop) boundaryValues[boundaryValues.length - 1].isLastVisibleLine = true;
      const isDraggable = i === this.q.first_bin.stop || i === this.q.bin_size - 1;
      boundaryValues.push({ x: i, isDraggable, movesWithLineIndex: !isDraggable ? 0 : -1 });
    }
    if (this.q.last_bin) {
      boundaryValues.push({
        x: this.q.last_bin.start,
        isDraggable: true,
        isLastVisibleLine: true,
        movesWithLineIndex: -1
      });
    }
    return {
      values: boundaryValues,
      callback: (d, value) => {
        if (d.index === 0) {
          this.dom.first_stop_input.property("value", value);
          this.q.first_bin.stop = value;
        } else {
          this.editHandler.handler.dom.last_start_input.property("value", value);
          if (this.q.last_bin) this.q.last_bin.start = value;
        }
      }
    };
  }
  getEditedQ(destroyDom = true) {
    const bin_size = this.dom.bin_size_input.property("value");
    const config = {
      mode: "discrete",
      type: "regular-bin",
      startinclusive: this.editHandler.boundaryInclusion == "startinclusive",
      stopinclusive: this.editHandler.boundaryInclusion == "stopinclusive",
      bin_size: Number(bin_size),
      first_bin: {
        startunbounded: true,
        stop: Number(this.dom.first_stop_input.property("value"))
      },
      rounding: bin_size.includes(".") && !bin_size.endsWith(".") ? `.${bin_size.split(".")[1].length}f` : ".0f"
    };
    if (this.dom.fixed_radio.property("checked")) {
      config.last_bin = {
        start: Number(this.dom.last_start_input.property("value")),
        stopunbounded: true
      };
    }
    if (destroyDom) {
      for (const name of Object.keys(this.dom)) {
        this.dom[name].remove();
        delete this.dom[name];
      }
    }
    return config;
  }
  undoEdits() {
    this.q = this.getDefaultQ();
    this.dom.binsTable.selectAll("*").remove();
    this.renderBinSizeInput(this.dom.binsTable.append("tr"));
    this.renderFirstBinInput(this.dom.binsTable.append("tr"));
    this.renderLastBinInputs(this.dom.binsTable.append("tr"));
    this.editHandler.handler.density.setBinLines(this.getBoundaryOpts());
  }
};

export {
  NumRegularBinEditor
};
//# sourceMappingURL=chunk-QQZ3SBF3.js.map
