import {
  urlmap_default
} from "./chunk-WKNI3HRQ.js";
import {
  addGeneSearchbox,
  first_genetrack_tolist,
  keyupEnter,
  make_one_checkbox,
  renderTable,
  sayerror,
  string2variant,
  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 "./chunk-M3J4MINX.js";
import "./chunk-PF4DSFDR.js";
import "./chunk-QH6W3NVF.js";
import "./chunk-NOEAT6CX.js";
import {
  contigNameNoChr2,
  mclass
} 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";

// gdc/bam.js
var tip = new Menu({ padding: "" });
var gdc_genome = "hg38";
var gdcDslabel = "GDC";
var variantFlankingSize = 60;
var baminfo_cols = [
  { title: "Entity ID", key: "entity_id" },
  { title: "Experimental Strategy", key: "experimental_strategy" },
  { title: "Tissue Type", key: "tissue_type" },
  { title: "Tumor Descriptor", key: "tumor_descriptor" },
  { title: "Size", key: "file_size", width: "10vw" }
];
var ssmTableColumns = [
  { label: "Gene", width: "10vw", sortable: true },
  { label: "Mutation" },
  { label: "Consequence", sortable: true },
  { label: "Position" }
];
var noPermissionMessage = "You are attempting to access a Sequence Read file that you are not authorized to access. <a href=https://gdc.cancer.gov/access-data/obtaining-access-controlled-data target=_blank>Please request dbGaP Access to the project</a>.";
async function bamsliceui({ filter0, hideTokenInput = false, callbacks = {}, stream2download = false, inputValue, debugmode = false }, holder, genomes) {
  if (callbacks.postRender && typeof callbacks.postRender != "function") throw "callbacks.postRender is not function";
  const publicApi = {
    dom: {
      tip
    }
  };
  const genome = genomes[gdc_genome];
  if (!genome) throw "missing genome for " + gdc_genome;
  const gdc_args = {
    bam_files: [],
    runFlags: {
      // presence of a flag indicates the corresponding ui component is not finished loading yet
      runflag_caseFileList: 1,
      runflag_gdcInput: 1
    }
  };
  const urlp = urlmap_default();
  const backBtnDiv = holder.append("div").style("margin-left", "30px").style("display", "none");
  backBtnDiv.append("button").html("&#171; Back To Input Form").on("click", () => {
    backBtnDiv.style("display", "none");
    blockHolder.style("display", "none").selectAll("*").remove();
    formdiv.style("display", "block");
  });
  const formdiv = holder.append("div").style("margin-left", "30px");
  const formDiv = formdiv.append("div");
  const blockHolder = holder.append("div").style("display", "none");
  if (!hideTokenInput) makeTokenInput();
  const gdcid_input = await makeGdcIDinput();
  const ssmGeneDiv = formdiv.append("div").style("padding", "3px 10px").style("display", "none");
  const [submitButton, saydiv, noPermissionDiv] = makeSubmitAndNoPermissionDiv();
  const defaultSearchString = inputValue || urlp.get("gdc_id");
  if (defaultSearchString) {
    gdcid_input.property("value", defaultSearchString).node().dispatchEvent(new Event("search"));
  } else {
    delete gdc_args.runFlags.runflag_gdcInput;
    runCallbackAfterUIupdate();
  }
  function runCallbackAfterUIupdate() {
    if (!callbacks.postRender) return;
    if (Object.keys(gdc_args.runFlags).length == 0) {
      callbacks.postRender(publicApi);
    } else {
    }
  }
  function makeTokenInput() {
    const tr = formDiv.insert("div").attr("class", "sja-gdcbam-tokendiv");
    tr.insert("div").style("display", "inline-block").style("width", "15vw").text("GDC Token File");
    const td = tr.insert("div").style("display", "inline-block");
    const input = td.append("input").attr("type", "file").attr("aria-label", "GDC token file");
    const file_error_div = td.append("span").style("margin-left", "20px").style("display", "none");
    input.on("change", (event) => {
      const file = event.target.files[0];
      if (!file) {
        input.property("value", "");
        return;
      }
      if (!file.size) {
        input.property("value", "");
        show_input_check(file_error_div, "Blank file " + file.name);
        return;
      }
      const reader = new FileReader();
      reader.onload = (event2) => {
        const text = event2.target.result.trim();
        if (text.length < 100) {
          input.property("value", "");
          show_input_check(file_error_div, "Does not look like a toke file (content too short)");
          return;
        }
        if (text.length > 1e3) {
          input.property("value", "");
          show_input_check(file_error_div, "Does not look like a toke file (content too long)");
          return;
        }
        gdc_args.gdc_token = text;
      };
      reader.onerror = function() {
        input.property("value", "");
        show_input_check(file_error_div, "Error reading file " + file.name);
        return;
      };
      show_input_check(file_error_div);
      reader.readAsText(file, "utf8");
    });
    setTimeout(() => input.node().focus(), 1100);
  }
  async function makeGdcIDinput() {
    const tr = formDiv.insert("div");
    tr.append("div").style("display", "inline-block").style("width", "15vw").style("padding-top", "5px").text("Enter Search String").style("vertical-align", "top");
    const td = tr.append("div").style("display", "inline-block");
    const gdcid_input2 = td.append("input").attr("type", "search").attr("size", 45).attr("aria-label", "Specify File Name / File UUID / Case ID / Case UUID").style("padding", "3px 10px").property("placeholder", "File Name / File UUID / Case ID / Case UUID").attr("class", "sja-gdcbam-input").attr("data-testid", "sjpp-gdcbam-fileSearchInput").on("search", searchByGdcInputString).on("keyup", (event) => {
      if (keyupEnter(event)) {
        searchByGdcInputString();
        return;
      }
      gdc_loading.style("display", "").text("Press ENTER to search");
      gdcid_error_div.style("display", "none");
    });
    const gdc_loading = td.append("span").style("padding-left", "10px").style("display", "none");
    const gdcid_error_div = td.append("span").attr("class", "sja-gdcbam-gdcid_error_div").style("display", "none").style("padding", "2px 5px");
    td.append("br");
    const listCaseFileHandle = td.append("div").attr("class", "sja-gdcbam-listCaseFileHandle").style("margin", "5px").style("display", "inline-block").text("Looking for BAM files from current cohort...");
    queryCaseFileList(listCaseFileHandle);
    const userHasNoAccessDiv = td.append("div").style("display", "none").style("width", "500px").style("margin", "20px 3px").html(noPermissionMessage);
    const baminfo_div = formdiv.append("div").style("display", "none").style("margin", "20px 20px 20px 40px");
    const baminfo_table = baminfo_div.append("div").attr("class", "sja-gdcbam-onefiletable").style("display", "none");
    const bamselection_table = baminfo_div.append("div").attr("class", "sja-gdcbam-multifiletable").style("display", "none");
    publicApi.update = (_arg) => {
      searchByGdcInputString(null, _arg?.filter0 || filter0);
      queryCaseFileList(listCaseFileHandle, _arg?.filter0 || filter0);
    };
    async function searchByGdcInputString(eventNotUsed, filter0override) {
      saydiv.selectAll("*").remove();
      noPermissionDiv.style("display", "none");
      submitButton.style("display", "inline-block");
      submitButton.property("disabled", true);
      delete gdc_args.coordInput;
      delete gdc_args.ssmInput;
      gdcid_error_div.style("display", "none");
      gdc_loading.style("display", "none");
      try {
        await searchByGdcInputString_actual(
          Object.keys(filter0override || {}).length ? filter0override : filter0 || null
        );
      } catch (e) {
        show_input_check(gdcid_error_div, e.message || e);
        baminfo_div.style("display", "none");
        ssmGeneDiv.style("display", "none");
      }
      runCallbackAfterUIupdate();
    }
    async function searchByGdcInputString_actual(_filter0) {
      const gdc_id = gdcid_input2.property("value").trim();
      if (!gdc_id.length) {
        baminfo_div.style("display", "none");
        saydiv.selectAll("*").remove();
        ssmGeneDiv.style("display", "none");
        return;
      }
      gdcid_input2.attr("disabled", 1);
      gdc_loading.style("display", "").text("Loading...");
      gdc_args.runFlags.runflag_gdcInput = 1;
      const body = { gdc_id };
      if (_filter0) body.filter0 = _filter0;
      let data;
      try {
        data = await dofetch3("gdcbam", { body });
      } catch (e) {
        throw e;
      } finally {
        delete gdc_args.runFlags.runflag_gdcInput;
      }
      gdcid_input2.attr("disabled", null);
      gdc_loading.style("display", "none");
      gdc_args.bam_files = [];
      if (data.error) throw "Error: " + data.error;
      if (!Array.isArray(data.file_metadata)) throw "Error: .file_metadata[] missing";
      if (data.file_metadata.length == 0) {
        if (data.numFilesSkippedByWorkflow) {
          throw `File${data.numFilesSkippedByWorkflow > 1 ? "s" : ""} not viewable due to workflow type.`;
        }
        throw "No viewable BAM files found";
      }
      userHasNoAccessDiv.style("display", data.userHasNoAccess ? "block" : "none");
      gdc_args.case_id = data.file_metadata[0].case_id;
      if (data.file_metadata.length == 1) {
        update_singlefile_table(data, gdc_id);
      } else {
        update_multifile_table(data.file_metadata);
      }
      show_input_check(gdcid_error_div);
      gdc_args.runFlags.ssmSearch = 1;
      try {
        await makeSsmGeneSearch();
      } catch (e) {
        throw e;
      } finally {
        delete gdc_args.runFlags.ssmSearch;
      }
    }
    function update_singlefile_table(data, gdc_id) {
      baminfo_div.style("display", "block");
      baminfo_table.style("display", "block").selectAll("*").remove();
      bamselection_table.style("display", "none");
      const onebam = data.file_metadata[0];
      const file = {
        file_id: onebam.file_uuid,
        track_name: onebam.entity_id,
        // assign track name as entity_id
        about: []
      };
      gdc_args.bam_files.push(file);
      const table = table2col({ holder: baminfo_table });
      for (const col of baminfo_cols) {
        const [td1, td2] = table.addRow();
        td1.text(col.title);
        td2.html(
          col.url ? `<a href=${col.url}${onebam.file_uuid} target=_blank>${onebam[col.key]}</a>` : onebam[col.key]
        );
        const id = file.about.push({ k: col.title, v: onebam[col.key] });
      }
      baminfo_table.select("input").node()?.focus();
    }
    function update_multifile_table(files) {
      const columns = baminfo_cols.map((i) => {
        return { label: i.title, width: i.width };
      });
      const rows = [];
      for (const [i, onebam] of files.entries()) {
        const row = [];
        const elemId = onebam.entity_id;
        row.ariaLabelledBy = elemId;
        for (const column of baminfo_cols) {
          const value = onebam[column.key];
          if (column.url) {
            row.push({ html: `<a href=${row.url}${onebam.file_uuid} target=_blank>${value}</a>` });
          } else if (column.key == "entity_id") {
            row.push({ value, elemId });
          } else {
            row.push({ value });
          }
        }
        rows.push(row);
      }
      baminfo_div.style("display", "block");
      bamselection_table.style("display", "block").selectAll("*").remove();
      baminfo_table.style("display", "none");
      renderTable({
        rows,
        columns,
        div: bamselection_table,
        singleMode: stream2download ? true : false,
        // if true, display radio to only select 1 for download; otherwise allow to selec >1 for viz
        dataTestId: "sjpp-gdcbam-multiFileTable",
        noButtonCallback: (i, node) => {
          const onebam = files[i];
          if (stream2download) {
            gdc_args.bam_files = [
              {
                file_id: onebam.file_uuid,
                track_name: `${onebam.tissue_type}, ${onebam.tumor_descriptor}, ${onebam.experimental_strategy}, ${onebam.entity_id}`,
                about: baminfo_cols.map((i2) => {
                  return { k: i2.title, v: onebam[i2.key] };
                })
              }
            ];
          } else {
            if (node.checked) {
              gdc_args.bam_files.push({
                file_id: onebam.file_uuid,
                track_name: `${onebam.tissue_type}, ${onebam.tumor_descriptor}, ${onebam.experimental_strategy}, ${onebam.entity_id}`,
                about: baminfo_cols.map((i2) => {
                  return { k: i2.title, v: onebam[i2.key] };
                })
              });
            } else {
              gdc_args.bam_files = gdc_args.bam_files.filter((f) => f.file_id != onebam.file_uuid);
            }
          }
        }
      });
    }
    return gdcid_input2;
  }
  async function queryCaseFileList(handle, filter0override) {
    gdc_args.runFlags.runflag_caseFileList = 1;
    try {
      await queryCaseFileList_actual(handle, filter0override);
    } catch (e) {
      handle.text(e.message || e);
    } finally {
      delete gdc_args.runFlags.runflag_caseFileList;
    }
    runCallbackAfterUIupdate();
  }
  async function queryCaseFileList_actual(handle, filter0override) {
    const _filter0 = Object.keys(filter0override || {}).length ? filter0override : filter0 || null;
    const body = {};
    if (_filter0) body.filter0 = _filter0;
    const data = await dofetch3("gdcbam", { body });
    if (data.error) throw data.error;
    if (typeof data.case2files != "object") throw "wrong return";
    if (!data.restapihost) throw "data.restapihost is missing";
    gdc_args.restapihost = data.restapihost;
    handle.text(`Or, Browse ${data.total} Available BAM Files`).attr("data-testid", "sjpp-gdcbam-availableBamFileHandleIsReady");
    const assays = /* @__PURE__ */ new Map();
    for (const c in data.case2files) {
      for (const f of data.case2files[c]) {
        const e = f.experimental_strategy;
        if (!assays.has(e)) {
          assays.set(e, { count: 1, checked: true });
        } else {
          assays.get(e).count += 1;
        }
      }
    }
    let lastTabbedTime = Date.now();
    handle.classed("sja_clbtext", true).attr("tabindex", 0).on("keyup", (event) => {
      if (event.key == "Enter") {
        event.target.click();
      }
    }).on("click", (event) => {
      tip.clear().showunder(event.target);
      {
        const row = tip.d.append("div").style("margin", "10px");
        for (const [k, o] of assays) {
          make_one_checkbox({
            holder: row,
            labeltext: `${k}, ${o.count}`,
            divstyle: { display: "inline", "margin-right": "15px" },
            checked: o.checked,
            callback: () => {
              o.checked = !o.checked;
              makeTable(tableDiv);
            }
          });
        }
        row.select("input").on("keydown", (event2) => {
          if (event2.key == "Tab" && event2.shiftKey) lastTabbedTime = Date.now();
        }).on("blur", () => {
          if (Date.now() - lastTabbedTime > 500) return;
          handle.node().focus();
          tip.hide();
        }).node().focus();
      }
      const tableDiv = tip.d.append("div");
      makeTable(tableDiv);
    });
    function makeTable(tableDiv) {
      tableDiv.selectAll("*").remove();
      const rows = [];
      for (const caseName in data.case2files) {
        const files = data.case2files[caseName].filter((f) => assays.get(f.experimental_strategy).checked);
        if (files.length == 0) continue;
        for (const f of files) {
          rows.push([
            { value: caseName, data: f },
            { value: f.tissue_type },
            { value: f.tumor_descriptor },
            { value: f.experimental_strategy },
            { value: f.file_size }
          ]);
        }
      }
      renderTable({
        rows,
        columns: [
          { label: "Case", sortable: true },
          { label: "Tissue Type", sortable: true },
          { label: "Tumor Descriptor", sortable: true },
          { label: "Assay", sortable: true },
          { label: "File Size" }
          // barplot doesn't handle well size data range from mb to gb
        ],
        header: { allowSort: true },
        div: tableDiv,
        noButtonCallback: (i, node) => {
          tip.hide();
          gdcid_input.property("value", rows[i][0].data.file_uuid).node().dispatchEvent(new Event("search"));
        },
        singleMode: true,
        dataTestId: "sjpp-gdcbam-orBrowseFileTable"
      });
    }
  }
  async function makeSsmGeneSearch() {
    delete gdc_args.ssmInput;
    ssmGeneDiv.style("display", "block").selectAll("*").remove();
    const mutationMsgDiv = ssmGeneDiv.append("p").text("Searching for mutations...");
    const data = await dofetch3("termdb/singleSampleMutation", {
      body: {
        /* knowing that the query id is already case uuid, this prefix signals this to backend gdc code and thus no need for backend to sniff out if is case or sample id, which requires complete cache
        use non-alphabetic characters so no need to worry about lower/upper case
        this helps when backend caseid caching is incomplete, or truncated on dev machines
        this is harmless and do not impact non-gdc code
        */
        sample: "___" + gdc_args.case_id,
        genome: gdc_genome,
        dslabel: gdcDslabel
      }
    });
    if (data.error) throw data.error;
    const ssmLst = data.mlst.filter((m) => m.dt == 1);
    if (ssmLst.length == 0) {
      mutationMsgDiv.text("No mutations from this case.");
      if (stream2download) {
        const tabs2 = [
          {
            label: "Gene or position",
            testid: "sjpp-gdcbam-afterfindingcasetab-geneorpos",
            callback: () => {
              gdc_args.useSsmOrGene = "gene";
              submitButton.property("disabled", !gdc_args.coordInput?.chr);
            }
          },
          {
            label: "Unmapped reads",
            testid: "sjpp-gdcbam-afterfindingcasetab-unmapped",
            callback: () => {
              gdc_args.useSsmOrGene = "unmapped";
              submitButton.property("disabled", false);
            }
          }
        ];
        new Tabs({ holder: ssmGeneDiv, tabs: tabs2 }).main();
        await temp_renderGeneSearch(tabs2[0].contentHolder);
        tabs2[1].contentHolder.append("p").text("Only download unmapped reads from this BAM file.");
      } else {
        await temp_renderGeneSearch(ssmGeneDiv.append("div"));
      }
      return;
    }
    mutationMsgDiv.remove();
    const tabs = [
      {
        label: `${ssmLst.length} mutations${data.dt2total?.[0] ? " (" + data.dt2total[0].total + " total)" : ""}`,
        testid: "sjpp-gdcbam-afterfindingcasetab-ssm",
        callback: () => {
          gdc_args.useSsmOrGene = "ssm";
          submitButton.property("disabled", !gdc_args.ssmInput?.chr);
        }
      },
      {
        label: "Gene or position",
        testid: "sjpp-gdcbam-afterfindingcasetab-geneorpos",
        callback: () => {
          gdc_args.useSsmOrGene = "gene";
          submitButton.property("disabled", !gdc_args.coordInput?.chr);
        }
      }
    ];
    if (stream2download) {
      tabs.push({
        label: "Unmapped reads",
        testid: "sjpp-gdcbam-afterfindingcasetab-unmapped",
        callback: () => {
          gdc_args.useSsmOrGene = "unmapped";
          submitButton.property("disabled", false);
        }
      });
    }
    new Tabs({ holder: ssmGeneDiv, tabs }).main();
    temp_renderSsmList(tabs[0].contentHolder, ssmLst);
    await temp_renderGeneSearch(tabs[1].contentHolder);
    if (tabs[2]) tabs[2].contentHolder.append("p").text("Only download unmapped reads from this BAM file.");
  }
  function temp_renderSsmList(div, mlst) {
    const gene2mlst = /* @__PURE__ */ new Map();
    for (const m of mlst) {
      if (!gene2mlst.has(m.gene)) gene2mlst.set(m.gene, []);
      gene2mlst.get(m.gene).push(m);
    }
    const rows = [];
    for (const [gene, mlst2] of gene2mlst) {
      for (const m of mlst2) {
        const row = [];
        const elemId = `${gene}-${m.mname}`.replace(/\W+/g, "_");
        row.ariaLabelledBy = elemId;
        row.push({ value: gene, data: m });
        row.push({ value: m.mname, elemId });
        row.push({ value: mclass[m.class]?.label || "Unknown" });
        row.push({ value: m.chr + ":" + m.pos + " " + m.ref + ">" + m.alt });
        rows.push(row);
      }
    }
    renderTable({
      rows,
      columns: ssmTableColumns,
      header: { allowSort: true },
      div,
      noButtonCallback: (i, node) => {
        const m = rows[i][0].data;
        gdc_args.ssmInput = {
          chr: m.chr,
          pos: m.pos - 1,
          // convert 1-based to 0-based
          ref: m.ref,
          alt: m.alt
        };
        submitButton.property("disabled", false);
      },
      dataTestId: "sjpp-gdcbam-ssmTable",
      singleMode: true
    });
    if (urlp.has("gdc_ssm")) {
      for (const [gene, mlst2] of gene2mlst) {
        for (const m of mlst2) {
          if (m.mname == urlp.get("gdc_ssm")) {
            gdc_args.ssmInput = {
              chr: m.chr,
              pos: m.pos - 1,
              // convert 1-based to 0-based
              ref: m.ref,
              alt: m.alt
            };
            submitButton.property("disabled", false);
          }
        }
      }
    }
    div.select("input").node().focus();
  }
  async function temp_renderGeneSearch(div) {
    const geneSearchRow = div.append("div").style("display", "grid").style("grid-template-columns", "300px auto");
    geneSearchRow.append("div").text("Enter gene, position, SNP, or variant");
    gdc_args.coordInput = addGeneSearchbox(await makeArg_geneSearchbox(geneSearchRow));
    geneSearchInstruction(div);
  }
  async function makeArg_geneSearchbox(div) {
    const opt = {
      genome,
      tip,
      row: div.append("div"),
      allowVariant: true,
      // after getting valid result from geneSearchbox, enable submit button
      callback: () => submitButton.property("disabled", false)
    };
    if (urlp.has("gdc_pos")) {
      const t = urlp.get("gdc_pos").split(/[:\-]/);
      if (t.length == 3) {
        opt.defaultCoord = {
          chr: t[0],
          start: Number(t[1]),
          stop: Number(t[2])
        };
      }
    } else if (urlp.has("gdc_var")) {
      const variant = await string2variant(urlp.get("gdc_var"), genome);
      if (variant) {
        opt.defaultCoord = variant;
      }
    }
    return opt;
  }
  function makeSubmitAndNoPermissionDiv() {
    const div = formdiv.append("div");
    const submitButton2 = div.insert("div").style("display", "inline-block").append("button").attr("data-testid", "sjpp-gdcbam-submitBtn").style("margin", "20px 20px 20px 40px").style("padding", "10px 25px").style("border-radius", "35px").text("Submit").attr("disabled", true).on("click", async () => {
      if (JSON.parse(sessionStorage.getItem("optionalFeatures")).gdcBamDemoMode) {
        launchDemoMode();
        return;
      }
      try {
        saydiv2.selectAll("*").remove();
        validateInputs(gdc_args, genome, hideTokenInput);
        submitButton2.text("Loading ...");
        submitButton2.property("disabled", true);
        await sliceBamAndRender();
      } catch (e) {
        if (e == "Permission denied") {
          noPermissionDiv2.style("display", "inline-block");
          submitButton2.style("display", "none");
        } else {
          saydiv2.selectAll("*").remove();
          sayerror(saydiv2, e);
        }
      }
      submitButton2.text("Submit");
      submitButton2.property("disabled", false);
    });
    const saydiv2 = div.insert("div").style("display", "inline-block");
    const noPermissionDiv2 = div.insert("div").style("display", "none").style("margin", "20px");
    noPermissionDiv2.append("div").text("Access Alert").style("font-size", "1.5em").style("opacity", 0.4);
    noPermissionDiv2.append("div").style("border-top", "solid 1px #eee").style("border-bottom", "solid 1px #eee").style("padding", "20px 0px").style("margin-top", "5px").html(noPermissionMessage);
    return [submitButton2, saydiv2, noPermissionDiv2];
  }
  async function sliceBamAndRender() {
    const args = gdc_args;
    const par = {
      nobox: 1,
      genome,
      holder: blockHolder,
      debugmode
    };
    if (args.useSsmOrGene == "unmapped") {
      par.unmapped = 1;
    } else {
      if (args.position) {
        par.chr = args.position.chr;
        par.start = args.position.start;
        par.stop = args.position.stop;
      } else if (args.variant) {
        par.chr = args.variant.chr;
        par.start = args.variant.pos - variantFlankingSize;
        par.stop = args.variant.pos + variantFlankingSize;
      } else {
        throw "SV_EXPAND here";
      }
    }
    const headers = { "Content-Type": "application/json", Accept: "application/json" };
    if (args.gdc_token) {
      headers["X-Auth-Token"] = args.gdc_token;
    }
    for (const [idx, file] of args.bam_files.entries()) {
      submitButton.text(`Slicing BAM File ${idx + 1} of ${args.bam_files.length}...`);
      const body = {
        downloadgdc: 1,
        gdcFileUUID: file.file_id
      };
      if (par.unmapped) {
        body.gdcFilePosition = "unmapped";
        body.unmapped = 1;
      } else {
        body.gdcFilePosition = par.chr + ":" + par.start + "-" + par.stop;
        body.regions = [{ chr: par.chr, start: par.start, stop: par.stop }];
      }
      if (stream2download) {
        headers.compression = false;
        const url = `${gdc_args.restapihost}/slicing/view/${file.file_id}?region=${body.gdcFilePosition}`;
        const response = await fetch(url, { method: "GET", headers });
        const data = await response.blob();
        const a = document.createElement("a");
        a.href = URL.createObjectURL(data);
        if (par.unmapped) {
          a.download = file.track_name + ".unmapped.bam";
        } else {
          a.download = `${file.track_name}.${par.chr}.${par.start}.${par.stop}.bam`;
        }
        a.style.display = "none";
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        return;
      }
      const fileStat = await dofetch3("tkbam", { headers, body });
      if (fileStat.error) throw fileStat.error;
      {
        const i = file.about.find((i2) => i2.k == "Slice file size");
        if (i) i.v = fileStat.size;
        else file.about.push({ k: "Slice file size", v: fileStat.size });
      }
      if (fileStat.time) {
        const i = file.about.find((i2) => i2.k == "Stream time");
        if (i) i.v = Math.round(fileStat.time) + " seconds";
        else file.about.push({ k: "Stream time", v: Math.round(fileStat.time) + " seconds" });
      }
      if (fileStat.truncated) {
        if (!file.about.find((i) => i.k == "Truncated"))
          file.about.push({ k: "Truncated", v: "BAM slice size exceeds limit and is truncated" });
      } else {
        const i = file.about.findIndex((i2) => i2.k == "Truncated");
        if (i > 0) file.about.splice(i, 1);
      }
    }
    formdiv.style("display", "none");
    backBtnDiv.style("display", "block");
    blockHolder.style("display", "block");
    par.tklst = [];
    for (const file of args.bam_files) {
      const tk = {
        type: "bam",
        name: file.track_name || "Sample BAM slice",
        gdcToken: args.gdc_token,
        gdcFile: {
          uuid: file.file_id,
          // SV_EXPAND
          // tk remembers position for which slice is requested. this position is sent to backend to make the hashed cache file name persistent; must compose string consistently as chr:start-stop; using different separator will result in different hash
          position: par.chr + ":" + par.start + "-" + par.stop
        },
        aboutThisFile: file.about
      };
      if (args.variant) {
        tk.variants = [args.variant];
      }
      par.tklst.push(tk);
    }
    first_genetrack_tolist(genome, par.tklst);
    const _ = await import("./block-TTN2IQAH.js");
    new _.Block(par);
  }
  async function launchDemoMode() {
    formdiv.style("display", "none");
    backBtnDiv.style("display", "block");
    blockHolder.style("display", "block");
    blockHolder.append("div").style("margin", "25px").style("font-weight", "bold").text("Running in demo mode and showing non-GDC data.");
    const hg19 = genomes.hg19;
    const par = {
      nobox: 1,
      genome: hg19,
      holder: blockHolder,
      debugmode,
      chr: "chr17",
      start: 7578191,
      stop: 7578591,
      tklst: [
        {
          type: "bam",
          name: "Demo BAM Track",
          // can switch to other examples
          file: "proteinpaint_demo/hg19/bam/TP53_del.bam",
          variants: [{ chr: "chr17", pos: 7578382, ref: "AGCAGCGCTCATGGTGGGG", alt: "A" }]
        }
      ]
    };
    first_genetrack_tolist(hg19, par.tklst);
    par.tklst[1].name = "GENCODE";
    par.tklst[1].filterByName = `NM_000546
		NM_001126115`;
    const _ = await import("./block-TTN2IQAH.js");
    new _.Block(par);
  }
  return publicApi;
}
function geneSearchInstruction(d) {
  d.append("div").style("opacity", 0.7).html(`<ul>
		<li>Enter gene, position, SNP, or variant.
		The BAM file will be sliced at the given position and visualized.</li>
		<li>
			<span>Position</span>
			<ul><li>Example: chr17:7676339-7676767</li>
			    <li>Coordinates are hg38 and 1-based.</li>
			</ul>
		</li>
		<li>SNP example: rs28934574</li>
		<li>
			<span>Variant:</span>
			<ul>
			  <li>Example: chr2.208248388.C.T</li>
			  <li>Fields are separated by periods. Coordinate is hg38 and 1-based. Reference and alternative alleles are on forward strand.</li>
			</ul>
		</li>
		<li>
			<span>Supported HGVS formats for variants:</span>
			<ul>
			  <li>SNV: chr2:g.208248388C>T</li>
			  <li>MNV: chr2:g.119955155_119955159delinsTTTTT</li>
			  <li>Insertion: chr5:g.171410539_171410540insTCTG</li>
			  <li>Deletion: chr10:g.8073734delTTTAGA</li>
			</ul>
		</li>
		</ul>`);
}
function show_input_check(holder, error_msg) {
  holder.style("display", "inline-block").style("color", error_msg ? "red" : "green").html(error_msg ? "&#10060; " + error_msg : "&#10003;");
}
function validateInputs(args, genome, hideTokenInput = false) {
  if (!hideTokenInput) {
    if (!args.gdc_token) throw "GDC token missing";
    if (typeof args.gdc_token !== "string") throw "GDC token is not string";
  }
  if (!args.bam_files.length) throw "No BAM file selected";
  for (const file of args.bam_files) {
    if (!file.file_id) throw "file uuid is missing";
    if (typeof file.file_id !== "string") throw "file uuid is not string";
  }
  if (args.useSsmOrGene == "unmapped") {
    return;
  }
  delete args.position;
  delete args.variant;
  if (args.useSsmOrGene == "ssm") {
    const s = args.ssmInput;
    if (!s) throw "No variant selected";
    if (!s.chr) throw "ssmInput.chr missing";
    if (!Number.isInteger(s.pos)) throw "ssmInput.pos not integer";
    if (!s.ref) throw "ssmInput.ref missing";
    if (!s.alt) throw "ssmInput.alt missing";
    args.variant = s;
    return;
  }
  const ci = args.coordInput;
  if (!ci.chr) throw "No valid position or variant was entered";
  const [nocount, hascount] = contigNameNoChr2(genome, [ci.chr]);
  if (nocount + hascount == 0) throw "Invalid chromosome name: " + ci.chr;
  const chr = nocount ? "chr" + ci.chr : ci.chr;
  if (Number.isInteger(ci.pos)) {
    if (!ci.ref) throw "Reference allele missing from variant string";
    if (!ci.alt) throw "Alternative allele missing from variant string";
    args.variant = {
      chr,
      pos: ci.pos - 1,
      // convert 1-based to 0-based
      ref: ci.ref,
      alt: ci.alt
    };
  } else {
    if (!Number.isInteger(ci.start) || !Number.isInteger(ci.stop)) throw "non-integer start/stop";
    args.position = {
      chr,
      start: ci.start,
      stop: ci.stop
    };
  }
}
export {
  bamsliceui
};
//# sourceMappingURL=bam-QBO22VQB.js.map
