import {
  ABBREV_COHORT,
  getDefaultProfilePlotSettings,
  getProfilePlotConfig,
  makeChartBtnMenu,
  profilePlot
} from "./chunk-P3IENRWJ.js";
import {
  fillTwLst,
  renderTable
} from "./chunk-SA7APTJR.js";
import "./chunk-HJ6L54YS.js";
import "./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 {
  dofetch3
} from "./chunk-7EMWHCVW.js";
import "./chunk-7IYJZZQI.js";
import {
  copyMerge,
  getCompInit
} from "./chunk-M3J4MINX.js";
import "./chunk-PF4DSFDR.js";
import "./chunk-QH6W3NVF.js";
import "./chunk-NOEAT6CX.js";
import "./chunk-4UWS5Y3N.js";
import "./chunk-DD4R5P6W.js";
import "./chunk-JNITUVXP.js";
import {
  arc_default,
  line_default
} from "./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";

// plots/profile/radar2.ts
var ProfileRadar2 = class extends profilePlot {
  static {
    this.type = "profileRadar2";
  }
  constructor(opts) {
    super(opts, "profileRadar2");
    this.radius = 200;
    this.lineGenerator = line_default().defined((d) => d !== null);
    this.arcGenerator = arc_default().innerRadius(0);
  }
  async init(appState) {
    await super.init(appState);
    const config = appState.plots.find((p) => p.id === this.id);
    for (const row of config.terms) {
      this.scoreTerms.push(row.term1);
      this.scoreTerms.push(row.term2);
    }
    this.angle = Math.PI * 2 / config.terms.length;
  }
  async main() {
    await super.main();
    await this.setControls();
    this.plot();
  }
  /**
   * Override setControls() to fetch data from the dedicated radar2 route.
   * The base class setControls() builds filter UI and sets this.filter but
   * skips the data fetch for profileRadar2 (see profilePlot.ts).
   */
  async setControls(additionalInputs = []) {
    await super.setControls(additionalInputs);
    this.data = await this.fetchAggregatedScores();
    if (this.data && "error" in this.data) throw this.data.error;
  }
  async fetchAggregatedScores() {
    return dofetch3("termdb/profileRadar2Scores", {
      body: {
        genome: this.state.vocab.genome,
        dslabel: this.state.vocab.dslabel,
        scoreTerms: this.scoreTerms.map((t) => ({
          score: { term: { id: t.score.term.id }, q: t.score.q },
          maxScore: typeof t.maxScore === "number" ? t.maxScore : { term: { id: t.maxScore.term.id }, q: t.maxScore.q }
        })),
        filterByUserSites: this.settings?.filterByUserSites,
        filter: this.filter
      }
    });
  }
  plot() {
    const { radarG, rows, data, data2 } = this.createSvgAndGrid();
    this.drawLines(radarG, data, data2);
    this.drawPercentLabels(radarG);
    this.drawTableAndLegend(rows);
  }
  createSvgAndGrid() {
    const config = this.config;
    const width = this.isComparison ? 1e3 : 1050;
    const height = 650;
    this.dom.svg = this.dom.plotDiv.append("div").style("display", "inline-block").append("svg").attr("width", width).attr("height", height);
    const rightDiv = this.dom.plotDiv.append("div").style("display", "inline-block").style("vertical-align", "top").style("margin-top", "140px").style("margin-right", "20px");
    this.dom.tableDiv = rightDiv.append("div").attr("data-testid", "sjpp-profileRadar2-data-table");
    const x = 300;
    const y = 310;
    this.dom.svg.append("text").attr("transform", `translate(60, 40)`).attr("font-weight", "bold").attr("font-size", "0.9rem").text(config.title);
    const radarG = this.dom.svg.append("g").attr("transform", `translate(${x},${y})`);
    this.radarG = radarG;
    this.legendG = this.dom.svg.append("g").attr("data-testid", "sjpp-profileRadar2-legend").attr("transform", `translate(${x + 340},${y - 120})`);
    this.filterG = this.dom.svg.append("g").attr("transform", `translate(${x + 340},${y - 20})`);
    this.noteG = this.dom.svg.append("g").attr("transform", `translate(20, ${y + 150})`);
    for (let i2 = 0; i2 <= 10; i2++) this.drawPolygon(i2 * 10);
    const rows = [];
    const data = [];
    const data2 = [];
    const angle = this.angle;
    let i = 0;
    for (const { module, term1, term2 } of config.terms) {
      const iangle = i * angle - Math.PI / 2;
      const raw1 = this.getPercentage(term1);
      const raw2 = this.getPercentage(term2);
      const p1 = Number.isFinite(raw1) ? raw1 : null;
      const p2 = Number.isFinite(raw2) ? raw2 : null;
      this.radarG.append("path").datum({ module, percentage1: p1, percentage2: p2 }).attr("fill", "transparent").attr(
        "d",
        this.arcGenerator({
          outerRadius: this.radius,
          startAngle: i * angle - angle / 2,
          endAngle: (i + 1) * angle - angle / 2
        })
      ).on("click", (event) => this.onMouseOver(event));
      if (p2 !== null) this.addDataPoint("term2", p2, iangle, data2);
      else data2.push(null);
      if (p1 !== null) this.addDataPoint("term1", p1, iangle, data);
      else data.push(null);
      const color = term1.score.term.color;
      const bothPresent = p1 !== null && p2 !== null;
      const diff = bothPresent ? Math.abs(p1 - p2) : null;
      const diffRow = diff !== null ? { value: diff } : { value: "\u2014" };
      if (diff !== null && diff >= 20) diffRow.color = p2 > p1 ? "red" : "blue";
      rows.push([
        { color, disabled: true },
        { value: module },
        { value: p1 !== null ? p1 : "\u2014" },
        { value: p2 !== null ? p2 : "\u2014" },
        diffRow
      ]);
      this.drawModuleLabel(module, iangle);
      i++;
    }
    return { radarG, rows, data, data2 };
  }
  drawLines(radarG, data, data2) {
    const closePolygon = (arr) => {
      const firstDefined = arr.find((v) => v !== null);
      if (firstDefined) arr.push(firstDefined);
    };
    closePolygon(data);
    closePolygon(data2);
    const color1 = "blue";
    const color2 = "gray";
    radarG.append("g").append("path").style("stroke", color2).attr("fill", "none").style("stroke-dasharray", "5, 5").attr("stroke-width", "2px").attr("d", this.lineGenerator(data2));
    radarG.append("g").append("path").style("stroke", color1).attr("fill", "none").attr("stroke-width", "2px").attr("d", this.lineGenerator(data));
  }
  drawPercentLabels(radarG) {
    for (let i = 0; i <= 10; i++) {
      const percent = i * 10;
      radarG.append("text").attr("transform", `translate(0, ${-percent / 100 * this.radius - 2})`).attr("text-anchor", "end").style("font-size", "0.8rem").text(`${percent}%`).attr("pointer-events", "none");
    }
  }
  drawTableAndLegend(rows) {
    const config = this.config;
    const columns = [
      { label: "Color" },
      { label: "Module" },
      { label: config.term1.abbrev },
      { label: config.term2.abbrev },
      { label: "Difference*" }
    ];
    if (!this.isComparison) {
      renderTable({
        rows,
        columns,
        div: this.dom.tableDiv,
        showLines: true,
        resize: true,
        maxHeight: "60vh"
      });
      this.addDifferenceNote(
        `* Difference between ${config.term1.abbrev} and ${config.term2.abbrev}. If bigger than 20 and positive shown in blue, if negative shown in red.`
      );
      this.legendG.append("text").attr("text-anchor", "left").style("font-weight", "bold").text("Legend");
      let abbrev = config.term1.abbrev ? `(${config.term1.abbrev})` : "";
      this.addRadarLegendItem(`${config.term1.name} ${abbrev}`, "blue", 0, "none");
      abbrev = config.term2.abbrev ? `(${config.term2.abbrev})` : "";
      this.addRadarLegendItem(`${config.term2.name} ${abbrev}`, "gray", 1, "5, 5");
      if (this.state.activeCohort == ABBREV_COHORT) this.addEndUserImpressionNote(this.noteG);
      else this.addPOCNote(this.noteG);
    }
    this.addFilterLegend();
  }
  addDifferenceNote(text) {
    const noteDiv = this.dom.tableDiv.append("div").attr("data-testid", "sjpp-profileRadar2-difference-note").style("display", "flex").style("align-items", "center").style("gap", "6px").style("margin-top", "8px").style("font-size", "0.85em").style("font-style", "italic").style("color", "#555");
    noteDiv.append("span").attr("aria-hidden", "true").style("font-style", "normal").style("font-size", "1.1em").text("\u24D8");
    noteDiv.append("span").text(text);
  }
  drawModuleLabel(module, iangle) {
    const radius = this.radius;
    const leftSide = iangle > Math.PI / 2 && iangle <= 3 / 2 * Math.PI;
    const dx = radius * 1.1 * Math.cos(iangle);
    let dy = radius * 1.1 * Math.sin(iangle) - 10;
    const textElem = this.radarG.append("text").attr("x", `${dx}px`).attr("y", `${dy}px`).attr("font-size", "0.9em");
    const texts = module.split(" ");
    let span;
    for (const text of texts) {
      if (text != "and") {
        dy += 15;
        span = textElem.append("tspan").attr("x", `${dx}px`).attr("y", `${dy}px`).text(text);
      } else span.append("tspan").text(" and");
    }
    if (leftSide) textElem.attr("text-anchor", "end");
  }
  addDataPoint(field, percentage, iangle, data) {
    const iradius = percentage / 100 * this.radius;
    const x = iradius * Math.cos(iangle);
    const y = iradius * Math.sin(iangle);
    const color = field == "term1" ? "blue" : "#aaa";
    this.radarG.append("g").attr("transform", `translate(${x}, ${y})`).append("circle").attr("r", 4).attr("fill", color);
    data.push([x, y]);
  }
  drawPolygon(percent) {
    const data = [];
    for (let i = 0; i < this.config.terms.length; i++) {
      const iangle = i * this.angle - Math.PI / 2;
      const iradius = percent / 100 * this.radius;
      const x = iradius * Math.cos(iangle);
      const y = iradius * Math.sin(iangle);
      data.push([x, y]);
    }
    data.push(data[0]);
    this.radarG.append("g").append("path").style("stroke", "#aaa").attr("fill", "none").attr("d", this.lineGenerator(data)).style("opacity", "0.5");
  }
  addRadarLegendItem(text, color, index, strokeDash) {
    const step = 25;
    const y = step + index * step;
    const x = 35;
    this.legendG.append("path").attr("stroke", color).style("stroke-dasharray", strokeDash).attr("stroke-width", "2px").attr(
      "d",
      this.lineGenerator([
        [0, y - 5],
        [x, y - 5]
      ])
    );
    this.legendG.append("g").attr("transform", `translate(0, ${y - 5})`).append("circle").attr("r", 4).attr("fill", color);
    this.legendG.append("text").attr("font-size", "0.9em").attr("transform", `translate(${x + 5}, ${y})`).attr("text-anchor", "left").append("tspan").text(text);
  }
  onMouseOver(event) {
    const d = event.target.__data__;
    if (d?.module) {
      const label1 = this.config.term1.name;
      const label2 = this.config.term2.name;
      const menu = this.tip.clear();
      menu.d.append("div").style("font-weight", "bold").text(d.module);
      const table = menu.d.append("table");
      let tr = table.append("tr");
      tr.append("td").text(label1);
      tr.append("td").text(d.percentage1 ?? "\u2014");
      tr = table.append("tr");
      tr.append("td").text(label2);
      tr.append("td").text(d.percentage2 ?? "\u2014");
      menu.show(event.clientX, event.clientY, true, true);
    } else this.onMouseOut(event);
  }
};
async function getPlotConfig(opts, app, _activeCohort) {
  try {
    const activeCohort = _activeCohort === void 0 ? app.getState().activeCohort : _activeCohort;
    const defaults = await getProfilePlotConfig(activeCohort, app, opts);
    if (!defaults) throw "default config not found in termdbConfig.plotConfigByCohort.profileRadar2";
    defaults.settings = { profileRadar2: getDefaultProfilePlotSettings() };
    const config = copyMerge(structuredClone(defaults), opts);
    config.settings.controls = { isOpen: false };
    const twlst = [];
    for (const row of config.terms) {
      row.term1.score.q = { mode: "continuous" };
      twlst.push(row.term1.score);
      if (row.term1.maxScore.id) {
        row.term1.maxScore.q = { mode: "continuous" };
        twlst.push(row.term1.maxScore);
      }
      row.term2.score.q = { mode: "continuous" };
      twlst.push(row.term2.score);
      if (row.term2.maxScore.id) {
        row.term2.maxScore.q = { mode: "continuous" };
        twlst.push(row.term2.maxScore);
      }
    }
    await fillTwLst(twlst, app.vocabApi);
    return config;
  } catch (e) {
    throw `${e} [profileRadar2 getPlotConfig()]`;
  }
}
var profileRadar2Init = getCompInit(ProfileRadar2);
var componentInit = profileRadar2Init;
export {
  componentInit,
  getPlotConfig,
  makeChartBtnMenu,
  profileRadar2Init
};
//# sourceMappingURL=radar2-KREAMGVV.js.map
