import { extent, select, scaleLog, scaleLinear, axisBottom, axisLeft, line } from 'd3';
import { insertCSS } from './plotutil.js';
import { FFTResult } from './fft.js';

/*
 * Philip Crotwell
 * University of South Carolina, 2019
 * http://www.seis.sc.edu
 */
function createSimpleFFTPlot(cssSelector, fft, loglog = true) {
  let svg = createOverlayFFTPlot(cssSelector, [fft], loglog);
  svg.classed("overlayplot", false);
  return svg;
}
function createOverlayFFTPlot(cssSelector, fftArrays, loglog = true) {
  let ampPhaseList = [];
  let ampSliceMap = new Map();
  let maxFFTAmpLen = 0;
  let extentFFTData = null;
  let freqMinMax = [];

  for (const fftA of fftArrays) {
    if (loglog) {
      freqMinMax.push(fftA.fundamentalFrequency); // min freq
    } else {
      freqMinMax.push(0);
    }

    freqMinMax.push(fftA.sampleRate / 2); // max freq

    let ap;

    if (fftA instanceof FFTResult) {
      ap = fftA;
    } else {
      throw new Error("fftArrays must be array of FFTResult");
    }

    ampPhaseList.push(ap);

    if (maxFFTAmpLen < ap.amp.length) {
      maxFFTAmpLen = ap.amp.length;
    }

    let ampSlice;

    if (loglog) {
      // don't plot zero freq amp
      ampSlice = ap.amp.slice(1);
    } else {
      ampSlice = ap.amp;
    }

    let currExtent = extent(ampSlice);

    if (currExtent[0] === 0) {
      // replace zero with smallest non-zero / 10 for loglog plot
      currExtent[0] = 0.1 * ampSlice.reduce((acc, curr) => {
        if (curr > 0 && curr < acc) {
          return curr;
        } else {
          return acc;
        }
      }, 1e-9);
    }

    ampSliceMap.set(ap, ampSlice);

    if (extentFFTData) {
      extentFFTData = extent([extentFFTData[0], extentFFTData[1], currExtent[0], currExtent[1]], function (d) {
        return d;
      });
    } else {
      extentFFTData = currExtent;
    }
  }

  let svgParent = select(cssSelector);
  let svg = svgParent.append("svg");
  svg.classed("fftplot", true).classed("overlayplot", true);
  let margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50
  };
  let rect = svg.node().getBoundingClientRect();
  let width = +rect.width - margin.left - margin.right;
  let height = +rect.height - margin.top - margin.bottom;
  let g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  let x;

  if (loglog) {
    x = scaleLog().rangeRound([0, width]);
  } else {
    x = scaleLinear().rangeRound([0, width]);
  }

  x.domain(extent(freqMinMax));
  let y = scaleLog().rangeRound([height, 0]);
  y.domain(extentFFTData);

  if (y.domain()[0] === y.domain()[1]) {
    y.domain([y.domain()[0] / 2, y.domain()[1] * 2]);
  }

  g.append("g").attr("transform", "translate(0," + height + ")").call(axisBottom(x));
  g.append("g").attr("transform", "translate(0, ".concat(height + margin.bottom, " )")).append("text").attr("fill", "#000").attr("y", 0).attr("x", width / 2).attr("dy", "0.71em").attr("text-anchor", "end").text("Hertz");
  g.append("g").call(axisLeft(y));
  svg.append("g").attr("transform", "translate(0, ".concat(margin.top + height / 2, " )")).append("text").attr("fill", "#000").attr("dy", "0.71em").attr("transform", "rotate(-90)").attr("text-anchor", "end").text("Amp");
  let pathg = g.append("g").classed("allfftpaths", true);

  for (const ap of ampPhaseList) {
    let ampSlice = ampSliceMap.get(ap);
    let minFreq = ap.fundamentalFrequency;
    let line$1 = line();

    if (loglog) {
      line$1.x(function (d, i, a) {
        return x((i + 1) * minFreq);
      }); // minus one as slice off zero freq above
    } else {
      line$1.x(function (d, i, a) {
        return x(i * minFreq);
      });
    }

    line$1.y(function (d) {
      if (d !== 0.0 && !isNaN(d)) {
        return y(d);
      } else {
        return y.range()[0];
      }
    });
    pathg.append("g").append("path").classed("fftpath", true).datum(ampSlice).attr("d", line$1);
  }

  return svg;
}
const fftplot_css = "\n\n\npath.fftpath {\n  stroke: skyblue;\n  fill: none;\n  stroke-width: 1px;\n}\n\nsvg.fftplot {\n  height: 100%;\n  width: 100%;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+1) path.fftpath {\n  stroke: skyblue;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+2) path.fftpath {\n  stroke: olivedrab;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+3) path.fftpath {\n  stroke: goldenrod;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+4) path.fftpath {\n  stroke: firebrick;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+5) path.fftpath {\n  stroke: darkcyan;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+6) path.fftpath {\n  stroke: orange;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+7) path.fftpath {\n  stroke: darkmagenta;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+8) path.fftpath {\n  stroke: mediumvioletred;\n}\n\nsvg.fftplot.overlayplot g.allfftpaths g:nth-child(9n+9) path.fftpath {\n  stroke: sienna;\n}\n\n/* same colors for titles */\n\nsvg.fftplot.overlayplot g.title tspan:nth-child(9n+1)  {\n  fill: skyblue;\n}\n\nsvg.fftplot.overlayplot g.title text tspan:nth-child(9n+2)  {\n  stroke: olivedrab;\n}\n\nsvg.fftplot.overlayplot g.title text tspan:nth-child(9n+3)  {\n  stroke: goldenrod;\n}\n\nsvg.fftplot.overlayplot g.title tspan:nth-child(9n+4)  {\n  stroke: firebrick;\n}\n\nsvg.fftplot.overlayplot g.title tspan:nth-child(9n+5)  {\n  stroke: darkcyan;\n}\n\nsvg.fftplot.overlayplot g.title tspan:nth-child(9n+6)  {\n  stroke: orange;\n}\n\nsvg.fftplot.overlayplot g.title tspan:nth-child(9n+7)  {\n  stroke: darkmagenta;\n}\n\nsvg.fftplot.overlayplot g.title tspan:nth-child(9n+8)  {\n  stroke: mediumvioletred;\n}\n\nsvg.fftplot.overlayplot g.title tspan:nth-child(9n+9)  {\n  stroke: sienna;\n}\n\n\n/* links in svg */\nsvg.fftplot text a {\n  fill: #0000EE;\n  text-decoration: underline;\n}\n\n";

if (document) {
  insertCSS(fftplot_css);
}

export { createOverlayFFTPlot, createSimpleFFTPlot, fftplot_css };
//# sourceMappingURL=fftplot.js.map
