import {
  getDefaultGseaSettings
} from "./chunk-VHOEJBFP.js";
import "./chunk-UOVALHAJ.js";
import {
  PlotBase,
  getDefaultVolcanoSettings,
  sayerror,
  table2col
} from "./chunk-SA7APTJR.js";
import "./chunk-HJ6L54YS.js";
import "./chunk-LSEFWW72.js";
import "./chunk-SKREEF3H.js";
import {
  Menu
} from "./chunk-HYOEWQ5P.js";
import {
  Tabs
} from "./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 {
  NumericModes,
  PROTEOME_DAP
} from "./chunk-NOEAT6CX.js";
import {
  TermTypeGroups
} from "./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";

// plots/ProteomeInput.ts
var ProteomeInput = class _ProteomeInput extends PlotBase {
  static {
    this.type = "ProteomeInput";
  }
  constructor(opts, api) {
    super(opts, api);
    this.type = _ProteomeInput.type;
    this.opts = opts;
    this.components = {};
  }
  getState(appState) {
    const config = appState.plots.find((p) => p.id === this.id);
    if (!config) {
      throw `No plot with id='${this.id}' found. Did you set this.id before this.api = getComponentApi(this)?`;
    }
    return {
      config,
      activeCohort: appState.activeCohort,
      termdbConfig: appState.termdbConfig
    };
  }
  async init(appState) {
    const state = this.getState(appState);
    const proteomeDetails = state.config.proteomeDetails;
    const { organism, assay, cohort } = proteomeDetails;
    const organisms = state.termdbConfig?.queries?.proteome?.organisms || {};
    const cohortConfig = organisms[organism]?.assays?.[assay]?.cohorts?.[cohort];
    this.dom = this.initDom(proteomeDetails);
    this.tabs = [
      {
        label: "Single protein",
        isVisible: () => true,
        callback: async (_event, tab) => {
          await this.renderSingleProtein(tab, proteomeDetails, state.activeCohort);
          delete tab.callback;
        }
      },
      {
        label: "Two proteins",
        isVisible: () => true,
        callback: async (_event, tab) => {
          await this.renderTwoProteinSelect(tab, proteomeDetails, state.activeCohort);
          delete tab.callback;
        }
      },
      {
        label: "Hierarchical clustering",
        isVisible: () => true,
        callback: async (_event, tab) => {
          await this.renderMultiProteinSelect(tab, proteomeDetails, state.activeCohort);
          delete tab.callback;
        }
      },
      {
        label: "DAP Volcano",
        isVisible: () => !!cohortConfig?.DAPfile,
        callback: async (_event, tab) => {
          await this.renderDapVolcano(tab, proteomeDetails);
          delete tab.callback;
        }
      }
    ];
    const chartTabs = new Tabs({
      holder: this.dom.tabs,
      tabs: this.tabs,
      tabsPosition: "vertical"
    });
    await chartTabs.main();
  }
  initDom(proteomeDetails) {
    const { organism, assay, cohort } = proteomeDetails;
    this.opts.header.append("span").style("padding-right", "5px").text(`${organism} ${assay}: ${cohort}`);
    this.opts.header.append("span").text("PROTEOME").style("font-size", "0.7em").style("opacity", "0.6");
    return {
      tabs: this.opts.holder.append("div").style("margin", "10px").attr("data-testid", "sjpp-proteome-input-tabs-wrapper")
    };
  }
  getUsecase(proteomeDetails) {
    const { organism, assay, cohort } = proteomeDetails;
    return {
      target: "proteomeAbundance",
      detail: "term",
      proteomeDetails: { organism, assay, cohort },
      label: `Organism: ${organism}; Assay: ${assay}; Sample set: ${cohort}`
    };
  }
  async renderSingleProtein(tab, proteomeDetails, activeCohort) {
    const { organism, assay, cohort } = proteomeDetails;
    const row = tab.contentHolder.style("padding", "15px");
    row.append("div").style("padding", "5px").style("margin-bottom", "5px").text("Select a protein:");
    const treeHolder = row.append("div");
    const termdb = await import("./app-AIIN4WDE.js");
    termdb.appInit({
      vocabApi: this.app.vocabApi,
      holder: treeHolder,
      state: {
        activeCohort,
        nav: { header_mode: "search_only" },
        tree: { usecase: this.getUsecase(proteomeDetails) }
      },
      tree: {
        click_term: (term) => {
          const t = structuredClone(term.term || term);
          t.dataTypeDetails = { organism, assay, cohort };
          const config = {
            chartType: "summary",
            term: { term: t, q: { mode: NumericModes.continuous } },
            assayCohortTitle: `${organism} ${assay}: ${cohort}`,
            proteomeDetails: { organism, assay, cohort }
          };
          const overlayTerm = this.getState(this.app.getState()).termdbConfig?.queries?.proteome?.organisms?.[organism]?.overlayTerm;
          if (overlayTerm) config.term2 = { term: structuredClone(overlayTerm), q: {} };
          this.dispatchEdits(config);
        }
      }
    });
  }
  addProteinSearchbox(row, proteomeDetails, onSelect) {
    const usecase = this.getUsecase(proteomeDetails);
    const tip = new Menu({ padding: "0px" });
    const searchbox = row.append("input").attr("type", "search").attr("placeholder", "Protein").attr("class", "sja_genesearchinput").style("width", "200px");
    const mark = row.append("span").style("margin-left", "5px");
    const word = row.append("span").style("margin-left", "5px").style("font-size", ".8em").style("opacity", 0.6);
    let debounceTimer;
    const doSearch = async () => {
      const v = searchbox.property("value").trim();
      if (v.length < 2) {
        tip.hide();
        return;
      }
      try {
        const data = await this.app.vocabApi.findTerm(v, "", usecase, TermTypeGroups.PROTEOME_ABUNDANCE);
        if (!data.lst?.length) {
          mark.style("color", "red").html("&cross;");
          word.text("No match");
          tip.hide();
        } else {
          tip.clear().showunder(searchbox.node());
          for (const term of data.lst) {
            tip.d.append("div").attr("class", "sja_menuoption").style("border-radius", "0px").text(term.name).on("click", () => {
              tip.hide();
              searchbox.property("value", term.name);
              mark.style("color", "green").html("&check;");
              word.text(term.name);
              onSelect(term);
            });
          }
        }
      } catch (e) {
        mark.style("color", "red").html("&cross;");
        word.text(e.message || "Error");
      }
    };
    searchbox.on("keyup", async (event) => {
      if (event.key === "Escape") {
        tip.hide();
        return;
      }
      clearTimeout(debounceTimer);
      mark.html("");
      word.text("");
      debounceTimer = setTimeout(doSearch, 300);
    });
    return { searchbox, mark, word };
  }
  async renderTwoProteinSelect(tab, proteomeDetails, _activeCohort) {
    const { organism, assay, cohort } = proteomeDetails;
    const holder = tab.contentHolder.style("padding", "10px");
    let selectedTerm1 = null;
    let selectedTerm2 = null;
    const gene1row = holder.append("div").style("padding", "5px");
    const gene2row = holder.append("div").style("padding", "5px").style("display", "none");
    const submitBtn = holder.append("button").attr("type", "button").attr("disabled", true);
    gene1row.append("span").text("Select the first protein:");
    this.addProteinSearchbox(gene1row, proteomeDetails, (term) => {
      selectedTerm1 = term;
      gene2row.style("display", "block");
    });
    gene2row.append("span").text("Select the second protein:");
    this.addProteinSearchbox(gene2row, proteomeDetails, (term) => {
      selectedTerm2 = term;
      submitBtn.attr("disabled", null);
    });
    submitBtn.text("Submit").style("border", "none").style("border-radius", "20px").style("padding", "10px 15px").style("margin-top", "10px").on("click", async () => {
      if (!selectedTerm1 || !selectedTerm2) {
        sayerror(holder, "Please select two proteins.");
        return;
      }
      const t1 = structuredClone(selectedTerm1);
      const t2 = structuredClone(selectedTerm2);
      t1.dataTypeDetails = { organism, assay, cohort };
      t2.dataTypeDetails = { organism, assay, cohort };
      await this.dispatchEdits({
        chartType: "summary",
        term: { term: t1, q: { mode: NumericModes.continuous } },
        term2: { term: t2, q: { mode: NumericModes.continuous } },
        assayCohortTitle: `${organism} ${assay}: ${cohort}`,
        proteomeDetails: { organism, assay, cohort }
      });
    });
  }
  async renderMultiProteinSelect(tab, proteomeDetails, activeCohort) {
    const { organism, assay, cohort } = proteomeDetails;
    const holder = tab.contentHolder.style("padding", "10px");
    const usecase = this.getUsecase(proteomeDetails);
    const termdb = await import("./app-AIIN4WDE.js");
    const treeHolder = holder.append("div");
    termdb.appInit({
      vocabApi: this.app.vocabApi,
      holder: treeHolder,
      state: {
        activeCohort,
        nav: { header_mode: "search_only" },
        tree: { usecase }
      },
      tree: {
        submit_lst: (termlst) => {
          const twlst = termlst.map((term) => {
            const t = structuredClone(term);
            t.dataTypeDetails = { organism, assay, cohort };
            return { term: t, q: { mode: NumericModes.continuous } };
          });
          if (twlst.length < 3) {
            alert("At least three proteins are required for hierarchical clustering. Please select more proteins.");
            return;
          }
          this.dispatchEdits({
            chartType: "hierCluster",
            dataType: "proteomeAbundance",
            termgroups: [{ name: "Protein Abundance Cluster", lst: twlst, type: "hierCluster" }],
            assayCohortTitle: `${organism} ${assay}: ${cohort}`,
            proteomeDetails: { organism, assay, cohort }
          });
        }
      }
    });
    const enforceMinAndLayout = () => {
      const submitBtn = treeHolder.select("button").node();
      if (submitBtn) {
        const selectedCount = treeHolder.selectAll('.sja_menuoption[aria-label="Click to delete"]').size();
        submitBtn.disabled = selectedCount < 3;
      }
      const node = treeHolder.node();
      const divs = node.querySelectorAll("div");
      for (const div of divs) {
        if (div.style.flexWrap === "wrap" && div.style.display === "inline-block") {
          div.style.display = "flex";
        }
      }
    };
    const observer = new MutationObserver(enforceMinAndLayout);
    observer.observe(treeHolder.node(), {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ["style"]
    });
  }
  async renderDapVolcano(tab, proteomeDetails) {
    const { organism, assay, cohort } = proteomeDetails;
    const holder = tab.contentHolder.style("padding", "15px");
    const countsDiv = holder.append("div");
    countsDiv.append("span").text("Loading sample counts...");
    try {
      const result = await dofetch3("termdb/dapVolcano", {
        body: {
          genome: this.app.vocabApi.vocab.genome,
          dslabel: this.app.vocabApi.vocab.dslabel,
          organism,
          assay,
          cohort,
          countsOnly: true
        }
      });
      countsDiv.selectAll("*").remove();
      if (result.error) throw result.error;
      const table = table2col({ holder: countsDiv });
      table.table.style("margin-left", "5px").style("padding", "5px 10px");
      {
        const [c1, c2] = table.addRow();
        c1.html(`<span style="font-size:.8em;font-weight:bold">CONTROL</span>`);
        c2.html(`${result.sample_size1} samples`);
      }
      {
        const [c1, c2] = table.addRow();
        c1.html(`<span style="font-size:.8em;font-weight:bold">CASE</span>`);
        c2.html(`${result.sample_size2} samples`);
      }
    } catch (e) {
      countsDiv.selectAll("*").remove();
      countsDiv.append("span").style("color", "#999").text("Sample counts unavailable");
      console.error(e.stack);
    }
    holder.append("button").attr("class", "sjpp_apply_btn sja_filter_tag_btn sja_sharp_border").text("Launch Volcano").on("click", async () => {
      await this.dispatchEdits({
        chartType: "differentialAnalysis",
        childType: "volcano",
        termType: PROTEOME_DAP,
        headerText: `${organism} ${assay}: ${cohort}`,
        proteomeDetails: { organism, assay, cohort },
        settings: {
          volcano: {
            ...getDefaultVolcanoSettings({}, { termType: PROTEOME_DAP }),
            pValueType: "original"
          },
          gsea: getDefaultGseaSettings({})
        },
        highlightedData: [],
        hidePlotFilter: true
      });
    });
  }
  async dispatchEdits(config) {
    await this.app.dispatch({
      type: "app_refresh",
      subactions: [
        { type: "plot_create", config },
        { type: "plot_delete", id: this.id }
      ]
    });
  }
  async main() {
  }
};
var proteomeInputInit = getCompInit(ProteomeInput);
var componentInit = proteomeInputInit;
function getPlotConfig(opts) {
  const config = {
    chartType: "ProteomeInput",
    hidePlotFilter: true
  };
  return copyMerge(config, opts);
}
export {
  ProteomeInput,
  componentInit,
  getPlotConfig,
  proteomeInputInit
};
//# sourceMappingURL=ProteomeInput-5KMNE3PZ.js.map
