{% if not included %}
{% extends 'index.html' %}

{% block title %}
Output
{% endblock title %}

{% endif %}


{% block head %}

  <!-- Externals -->
  <script src="https://d3js.org/d3.v7.min.js"></script>

{% endblock head %}

{% set included = True %}

{% block content %}

<div id="output" class="form mt-2 row">
  
  <div class="col">
    
    <figure class="card-1">
      
      <div id="output-card-1" class="card-img-top">
      </div>
      
      <figcaption class="card-body">
        <h5 class="card-title">test focus</h5>

      <fieldset>

        <div class="row mt-2">
          <div class="input-group col">
            <button data-control="get-output" class="btn btn-primary w-100" 
                    type="button">Update</button>
          </div>
          <label for="auto-output" class="col-2 col-form-label">Auto</label>
          <div class="input-group col">
            <span class="input-group-text">
              <input id="auto-output" class="form-check-input mt-0"
                     type="checkbox" checked>
            </span>
          </div>
        </div>

      <aside class="row">
        <small class="col text-success">
          values:
          <var data-status="sequencer-output"></var>
        </small>
      </aside>

      </fieldset>


        
      </figcaption>
      
    </figure>
    
    <!-- <figure class="card-2"> -->
      
    <!--   <div id="output-card-2" class="card-img-top"> -->
    <!--     matrice qui -->
    <!--   </div> -->
      
    <!--   <figcaption class="card-body"> -->
    <!--     <h5 class="card-title">qweqwe</h5> -->
        
    <!--     <fieldset class="row"> -->
          
    <!--     </fieldset>         -->
        
    <!--     <aside class="row mt-2"> -->
    <!--       aside -->
    <!--     </aside> -->
    <!--   </figcaption> -->
      
    <!-- </figure> -->

  </div>

</div>

<script>
/////////////////////////////////////////////////////////////////////

// Function to create a reusable line chart
function linepointChart(selector, data=null,
                         config={
                             margin:null,
                             xlabel:"x",
                             ylabel:"y",
                             xrange : null,
                             yrange : null,
                         },
                       ) {

    if (data===null)
        data = [{x:0, y:0}]
     
    
    const container = d3.select(selector);

    // Get the dimensions of the container
    const containerWidth = 400;
    const containerHeight = 250;

    // Set up dimensions based on the container size and margins
    const margin = config.margin || { top: 10, right: 10, bottom: 40, left: 50 };
    const width = containerWidth - margin.left - margin.right;
    const height = containerHeight - margin.top - margin.bottom;

    // Create the SVG container with viewBox
    const svg = container.append("svg")
        .attr("width", "100%")
        .attr("height", "100%")
        .attr("viewBox", `0 0 ${containerWidth} ${containerHeight}`)
        .attr("preserveAspectRatio", "xMidYMid meet")
        .append("g")
        .attr("transform", `translate(${margin.left},${margin.top})`);

    // Set up scales
    const xScale = d3.scaleLinear()
        .domain(d3.extent(data, d => d.x))
        .range([0, width]);

    let yScale = d3.scaleLinear()
        .domain(d3.extent(data, d => d.y))
        .range([height, 0]);

    // Create line generator
    const line = d3.line()
        .x(d => xScale(d.x))
        .y(d => yScale(d.y));

    // Draw line
    const linePath = svg.append("path")
        .attr("class", "line")
        .style("stroke", "steelblue")
        .style("fill", "transparent")
        .attr("d", line(data));

    // Draw points
    const pointsGroup = svg.append("g").attr("class", "points");
    let points = pointsGroup.selectAll("circle")
        .data(data)
        .enter().append("circle")
        .attr("cx", d => xScale(d.x))
        .attr("cy", d => yScale(d.y))
        .attr("r", 3)
        .style("fill", "steelblue");
    
    // Draw x-axis
    svg.append("g")
        .attr("class", "x-axis")
        .attr("transform", `translate(0, ${height})`)
        .call(d3.axisBottom(xScale))
        .append("text")
        .attr("x", width / 2)
        .attr("y", margin.bottom - 10)
        .attr("fill", "black")
        .text(config.xlabel || "X Axis");

    // Draw y-axis
    svg.append("g")
        .attr("class", "y-axis")
        .call(d3.axisLeft(yScale))
        .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", -margin.left)
        .attr("x", -height / 2)
        .attr("dy", "1em")
        .attr("fill", "black")
        .text(config.ylabel || "Y Axis");


function update(newData) {
    // Update scales with new data
    xScale.domain(d3.extent(newData, d => d.x));
    yScale.domain(d3.extent(newData, d => d.y));

        // Update x-axis
        svg.select(".x-axis")
            .transition()
            .call(d3.axisBottom(xScale));

        // Update y-axis
        svg.select(".y-axis")
            .transition()
            .call(d3.axisLeft(yScale));

    // Update line
    linePath.transition().attr("d", line(newData));

    // Update points
    points = points.data(newData);

    // Remove old points
    points.exit().remove();

    // Update existing points and add new points using join
    points = points.join(
        enter => enter.append("circle")
            .attr("r", 3)
            .style("fill", "steelblue")
            .attr("cx", d => xScale(d.x))
            .attr("cy", d => yScale(d.y)),
        update => update.transition()
            .attr("cx", d => xScale(d.x))
            .attr("cy", d => yScale(d.y))
    );
}

    // Function to show/hide the line
    function showLine(show) {
        linePath.style("display", show ? "initial" : "none");
    }

    // Function to show/hide the points
    function showPoints(show) {
        pointsGroup.style("display", show ? "initial" : "none");
    }

    // Function to show/hide the points
    function ylog(show) {

        yScale = show ? d3.scaleLog() : d3.scaleLinear()
        yScale
            .domain(d3.extent(data, d => d.y))
            .range([height, 0]);

        update(data)
        
    }

    // Return the update function and control functions for later use
    return { update, showLine, showPoints, ylog };
}


///////////////////////////////////////////////////////////////////////////////////////

// Function to create a reusable heatmap
function matrixChart(selector, data=null,
                         config={
                             margin:null,
                             xlabel:"x",
                             ylabel:"y",
                         },
                    ) {


    if (data===null)
        data = [[0,0.1,0.2],[0.3,0.4,0.5]]

    
  const container = d3.select(selector);

  // Get the dimensions of the container
  const containerWidth = 400;
  const containerHeight = 250;

  // Set up dimensions based on the container size and margins
  const margin = config.margin || { top: 10, right: 10, bottom: 40, left: 50 };
  const width = containerWidth - margin.left - margin.right;
  const height = containerHeight - margin.top - margin.bottom;

  // Get the dimensions of the data array
  const n = data.length;
  const m = data[0].length;

  // Ensure equal scaling for both axes to create square cells
  const cellSize = Math.min(width / m, height / n);

  // Create the SVG container with viewBox
  const svg = container
    .append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("viewBox", `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`)
    .attr("preserveAspectRatio", "xMidYMid meet")
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`);

    // Set up scales
    
    const xScale = d3.scaleLinear()
          .domain([1, m])
          .range([0, cellSize*m]);
    const yScale = d3.scaleLinear()
          .domain([1, n])
          .range([cellSize*n, 0]);

  // Set up color scale
    const colorScale = d3.scaleSequential(d3.interpolateCividis).domain([0, 1]);


    const valText = svg.append("text")
          .style("font-size","0.6em")
    
  // Draw heatmap rectangles
    const heatmapRects = svg.selectAll(".heatmap-rect")
    .data(data.flat()) // Flatten the 2D array into a 1D array
    .enter()
    .append("rect")
    .attr("data-value", d => d)
    .attr("class", "heatmap-rect")
    .attr("x", (_, i) => (i % m) * cellSize) // Compute x position from the flattened index
    .attr("y", (_, i) => Math.floor(i / m) * cellSize) // Compute y position from the flattened index
    .attr("width", cellSize)
    .attr("height", cellSize)
     .style("fill", d => colorScale(d))
        .on("mouseover", function(event, d) {
            valText.text(d.toFixed(2))
    })


    
  // Draw x-axis with ticks corresponding to cellSize
  svg.append("g")
    .attr("class", "x-axis")
    .attr("transform", `translate(0, ${cellSize*n})`)
    .call(d3.axisBottom(xScale))
   .append("text")
    .attr("x", cellSize*m / 2)
    .attr("y", margin.bottom - 10)
    .attr("fill", "black")
    .text(config.xlabel)
    
  // Draw y-axis with ticks corresponding to cellSize
  svg.append("g")
    .attr("class", "y-axis")
    .call(d3.axisLeft(yScale))
   .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", -margin.left)
    .attr("x", -cellSize*n / 2)
    .attr("dy", "1em")
    .attr("fill", "black")
    .text(config.ylabel);
    
  // Function to update the chart with new data
  function update(newData) {
    // Update heatmap rectangles
    heatmapRects.data(newData.flat())
      .transition()
      .style("fill", d => colorScale(d));

    // Update x-axis
    svg.select(".x-axis")
      .transition()
      .call(d3.axisBottom(xScale));

    // Update y-axis
    svg.select(".y-axis")
      .transition()
      .call(d3.axisLeft(yScale));
  }


    // Function to update the color scale dynamically
    function setColorScale(domain) {
        colorScale.domain(domain);
        // Update heatmap colors
        heatmapRects.transition().style("fill", d => colorScale(d));
    }
    
  // Return the update function and setColorScale function for later use
    return { update, setColorScale };
    
}

  

  const data = [{x:0, y:0}]
  const chart1 = linepointChart("#output-card-1");
  //  const chart2 = matrixChart("#output-card-2");

  $('[data-control="get-output"]').click(function(){

      $(this).crud("GET", "/api/sequencer/run", null, false).then(function(e){

          const focus = e.response.output.focus
          const data = focus.m2.map((x, i) => ({ x, y: focus.fwhm[i] }));
          chart1.update(data);
          
          // const residuals = e.response.output.residuals
          // chart2.update(residuals);
          
      })
  })
  

</script>

{% endblock content %}


{% block footer %}
{% endblock footer %}
