<template>
    <section id="beeswarm">
      <div id="text1" class="text-container">
        <p>
          Everyone needs access to clean water. People may be more vulnerable to water insecurity due to  
          <span 
            :class="['highlight', 'Demographiccharacteristics', { checked: isChecked.Demographiccharacteristics }]" 
            @click="toggleCategory('Demographiccharacteristics')"
          >
            demographic characteristics
          </span>,
          <span 
            :class="['highlight', 'Health', { checked: isChecked.Health }]" 
            @click="toggleCategory('Health')"
          >
            health
          </span>, 
          <span 
            :class="['highlight', 'Livingconditions', { checked: isChecked.Livingconditions }]" 
            @click="toggleCategory('Livingconditions')"
          >
            living conditions
          </span>, 
          <span 
            :class="['highlight', 'Socioeconomicstatus', { checked: isChecked.Socioeconomicstatus }]" 
            @click="toggleCategory('Socioeconomicstatus')"
          >
            socioeconomic status
          </span>,
          <span 
            :class="['highlight', 'Riskperception', { checked: isChecked.Riskperception }]" 
            @click="toggleCategory('Riskperception')"
          >
            risk perception
          </span>,
          <span 
            :class="['highlight', 'Landtenure', { checked: isChecked.Landtenure }]" 
            @click="toggleCategory('Landtenure')"
          >
            land tenure
          </span>, and 
          <span 
            :class="['highlight', 'Exposure', { checked: isChecked.Exposure }]" 
            @click="toggleCategory('Exposure')"
          >
            exposure to stressors
          </span> (like drought or pollution).
        </p>
      </div>
      <div id="beeswarm-chart-container">
        <div id="tooltip" style="position: absolute; opacity: 0;"></div>
      </div>
      <caption>
        A meta-analysis by Drakes et al. (2024) evaluated how water insecurity in the Western U.S. is influenced by social determinants. Interact with the chart and the highlighted text above to see what they found.
      </caption>
    </section>
  </template>
  
  <script setup>
  import { onMounted, ref, watch } from "vue";
  import * as d3 from 'd3';
  
  // Global variables 
  const publicPath = import.meta.env.BASE_URL;
  const dataSet1 = ref([]); 
  const dataSet2 = ref([]); 
  const selectedDataSet = ref('dataSet1');
  const data = ref([]);
  let simulation;
  
  // Set up SVG
  let svg;
  const height = 600;
  const width = 800;
  const margin = { top: 50, right: 20, bottom: 50, left: 50 };
  
  const isChecked = ref({
    Demographiccharacteristics: true,
    Health: true,
    Livingconditions: true,
    Socioeconomicstatus: true,
    Riskperception: true,
    Landtenure: true,
    Exposure: true
  });
  
  // Set colors for bubble charts
  const dimensionColors = {
    Demographiccharacteristics: "#092836",
    Landtenure: "#1b695e",
    Livingconditions: "#7a5195",
    Socioeconomicstatus: "#2a468f",
    Health: "#ef5675",
    Riskperception: "#ff764a",
    Exposure: "#ffa600"
  };
  
  // Load data and then make chart
  onMounted(async () => {
    try {
      await loadDatasets();
      data.value = selectedDataSet.value === 'dataSet1' ? dataSet1.value : dataSet2.value;
      if (data.value.length > 0) {
        createBeeswarmChart();
      } else {
        console.error('Error loading data');
      }
    } catch (error) {
      console.error('Error during component mounting', error);
    }
  });
  
  async function loadDatasets() {
    try {
      dataSet1.value = await loadData('determinant_uncertainty.csv');
      dataSet2.value = await loadData('indicator_uncertainty.csv');
      console.log('data in')
    } catch (error) {
      console.error('Error loading datasets', error);
    }
  }
  
  async function loadData(fileName) {
    try {
      const data = await d3.csv(publicPath + fileName, d => { 
        d.level_agreement = +(+d.level_agreement).toFixed(2); 
        d.evidence_val = +d.evidence_val; 
        d.sig_value = +d.sig_value; 
        return d;
      });
      return data;
    } catch (error) {
      console.error(`Error loading data from ${fileName}`, error);
      return [];
    }
  }
  // make beeswarm of determinants
  function createBeeswarmChart() {
    svg = d3
      .select('#beeswarm-chart-container')
      .append('svg')
      .attr('class', 'beeswarmSvg')
      .attr('width', width)
      .attr('height', height);
  
    const yScale = d3.scaleLinear()
      .domain([40, d3.max(data.value, d => d.level_agreement)])
      .range([height-margin.bottom, margin.top]);
    
    // Set radius based on evidence value
    const radiusScale = d3.scaleLinear()
      .domain([d3.min(data.value, d => d.evidence_val), d3.max(data.value, d => d.evidence_val)])
      .range([10, 70]);
  
    const yAxis = svg.append('g')
      .attr("transform", "translate(100, 0)")
      .call(d3.axisLeft(yScale).ticks(5))
      .attr("stroke-width", 2)
      .attr("font-size", 20);
  
    // Add label to y axis
    svg.append('text')
    .attr("class", "yLabel")
    .attr("text-anchor", "left")
    .attr("font-weight", 700)
    .attr("transform", `translate(${margin.left}, ${margin.top/2})`)
    .text("Level of Agreement");

    svg.append('text')
      .attr("class", "yLabel")
      .attr("text-anchor", "left")
      .attr("font-weight", 700)
      .attr("transform", `translate(${margin.left}, ${height - (margin.bottom/2) + 10})`)
      .text("Inconclusive");

  
    // Set forces
    const forceY = d3.forceY(d => yScale(d.level_agreement)).strength(0.7);
    const forceX = d3.forceX(margin.left + (width / 2)).strength(0.2);
    const forceCollide = d3.forceCollide(d => radiusScale(d.evidence_val) + 2).iterations(20);
    const forceManyBody = d3.forceManyBody().strength(1);
  
    const bubbles = svg
      .selectAll('.bubble')
      .data(data.value)
      .enter()
      .append('circle')
      .attr('class', 'bubble')
      .attr('r', d => radiusScale(d.evidence_val))
      .style('fill', d => dimensionColors[d.dimension.replace(' ', '')])
      .on('mouseover', function (event, d) {
        const [x, y] = d3.pointer(event);
        const tooltip = d3.select('#tooltip')

        tooltip.html('')
        tooltip.append('div')
          .html(`<strong>${d.determinant}</strong><br>appeared in ${d.evidence_val} ${d.evidence_val === 1 ? 'study' : 'studies'}`);

          // add stacked bar chart
          const barData = [
            { name: 'positive', value: d.pos_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: dimensionColors[d.dimension.replace(' ', '')]  },
            { name: 'negative', value: d.neg_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white'  },
            { name: 'unknown', value: d.unk_direction_total, pattern: true, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' }
          ];

          // Set dimensions for the bar chart
          const barWidth = 130;
          const barHeight = 10;

          // Create an SVG element for the bar chart
          const svgBar = tooltip.append('svg')
            .attr('width', barWidth + 10)
            .attr('height', barHeight + 10);

            const defs = svgBar.append('defs');

            const pattern = defs.append('pattern')
            .attr('id', 'pattern-stripe')
            .attr('patternUnits', 'userSpaceOnUse')
            .attr('width', 8)  // Adjusted to make pattern larger
            .attr('height', 8)

          pattern.append('rect')
            .attr('width', 8)
            .attr('height', 8)
            .attr('fill', 'white');

          pattern.append('path')
            .attr('d', 'M-2,2 l4,-4 M0,8 l8,-8 M6,10 l4,-4') // Adjusted path for thicker stripes
            .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
            .attr('stroke-width', 3);  // Thicker stripes

          const g = svgBar.append('g')
            .attr('transform', 'translate(8, 8)');

          // Create a scale for the x-axis
          const xBar = d3.scaleLinear()
            .domain([0, d3.sum(barData, d => d.value)])
            .range([0, barWidth]);

          // Create groups for each bar segment
          const barGroups = g.selectAll('g')
            .data(barData)
            .enter()
            .append('g');

          // Add the rectangles
          barGroups.append('rect')
            .attr('x', (d, i) => i > 0 ? xBar(d3.sum(barData.slice(0, i), d => d.value)) : 0)
            .attr('y', 0)
            .attr('width', d => xBar(d.value))
            .attr('height', barHeight)
            .style('fill', d => d.pattern ? 'url(#pattern-stripe)' : d.fill)
            .style('stroke', d => d.stroke ? d.stroke : 'none');

          // Position the tooltip
          tooltip
            .style('opacity', 1)
            .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
            .style('left', (x + 10) + 'px')
            .style('top', (y - 28) + 'px');

          // Highlight the circle
          d3.select(this)
            .attr('stroke', d => dimensionColors[d.dimension.replace(' ', '')])
            .attr('stroke-width', 15);
      })
      .on('mouseout', function () {
        d3.select('#tooltip').style('opacity', 0);
        d3.select(this)
          .attr('stroke', null)
          .attr('stroke-width', null);
      });
  
    // Run simulation
    simulation = d3.forceSimulation()
      .force('x', forceX)
      .force('y', forceY)
      .force('collide', forceCollide)
      .force('charge', forceManyBody)
      .nodes(data.value)
      .on('tick', ticked)
      .alpha(0.75)
      .alphaDecay(0.03);
  
      function ticked() {
        bubbles
          .attr("cx", d => Math.max(margin.left +radiusScale(d.evidence_val), Math.min(width - margin.right - radiusScale(d.evidence_val), d.x)))
          .attr("cy", d => Math.max(radiusScale(d.evidence_val), Math.min(height - radiusScale(d.evidence_val), d.y)))
          //.each(d => { d.y = Math.max(radiusScale(d.evidence_val), Math.min(height - radiusScale(d.evidence_val), yScale(d.level_agreement))); });
      }
  }
  
  function toggleCategory(category) {
    //console.log(`Toggle category called for: ${category}`);
    isChecked.value[category] = !isChecked.value[category];
    console.log(`Category toggled: ${category}, new value: ${isChecked.value[category]}`);
    updateChart();
  }
  
  function updateChart() {
    console.log('Update chart called');
    const yScale = d3.scaleLinear()
      .domain([40, d3.max(data.value, d => d.level_agreement)])
      .range([height-margin.bottom, margin.top]);
  
    // Set radius based on evidence value
    const radiusScale = d3.scaleLinear()
      .domain([d3.min(data.value, d => d.evidence_val), d3.max(data.value, d => d.evidence_val)])
      .range([10, 70]);

      // Filter data based on active categories
    const activeCategories = Object.keys(isChecked.value).filter(category => isChecked.value[category]);
    const dataPoints = data.value.filter(d => activeCategories.includes(d.dimension.replace(' ', '')));
    console.log('Active categories:', activeCategories);
    console.log('Filtered data points:', dataPoints);
  
    // Update existing bubbles and add new bubbles
    const bubbles = svg.selectAll(".bubble")
      .data(dataPoints, d => d.id);

    // Remove old bubbles
    bubbles.exit().remove();
    
    // Add new bubbles
    bubbles.enter()
      .append('circle')
      .attr('class', 'bubble')
      .attr('r', d => d3.select('.bubble').size() ? d3.select('.bubble').attr('r') : radiusScale(d.evidence_val))
      .style('fill', d => dimensionColors[d.dimension.replace(' ', '')])
      .attr('cx', d => d.x)  // Use existing x position
      .attr('cy', d => d.y)
      .merge(bubbles)  // Merge to apply forces to new and existing bubbles
      .attr('r', d => radiusScale(d.evidence_val))
      .style('fill', d => dimensionColors[d.dimension.replace(' ', '')]);

  }
  </script>
  
  <style scoped lang="scss">
  $switchWidth: 12rem;
  $Demographiccharacteristics: #092836;
  $Landtenure: #1b695e;
  $Livingconditions: #7a5195;
  $Socioeconomicstatus: #2a468f;
  $Health: #ef5675;
  $Riskperception: #ff764a;
  $Exposure: #ffa600;
  
  #beeswarm-chart-container {
      text-align: center;
      position: relative;
  }
  
  #beeswarm-chart-container svg {
      max-width: 100%;
      max-height: 100%;
      height: auto; /* Maintain aspect ratio */
      display: inline-block;
  }
  
  .bubble {
      stroke: black;
      stroke-width: 2px; 
      fill-opacity: 0.8; 
  }
  
  .chart-text {
      user-select: none;
  }
  .yLabel {
      font-weight: bold;
  }
  
  .highlight {
      color: white;
      padding: 0.25px 5px;
      border-radius: 10px;
      white-space: nowrap;
      font-weight: bold;
      cursor: pointer; /* Add cursor pointer for better UX */
      transition: all 0.1s; /* Smooth transition for background color and border */
  }
  
  .highlight:not(.checked) {
      background-color: white;
      border: 2px solid;
  }
  .highlight.Demographiccharacteristics {
      background-color: $Demographiccharacteristics;
  }
  .highlight.Demographiccharacteristics:not(.checked) {
      color: $Demographiccharacteristics;
      border-color: $Demographiccharacteristics;
  }
  .highlight.Landtenure {
      background-color: $Landtenure;
  }
  .highlight.Landtenure:not(.checked) {
      color: $Landtenure;
      border-color: $Landtenure;
  }
  .highlight.Livingconditions {
      background-color: $Livingconditions;
  }
  .highlight.Livingconditions:not(.checked) {
      color: $Livingconditions;
      border-color: $Livingconditions;
  }
  .highlight.Socioeconomicstatus {
      background-color: $Socioeconomicstatus;
  }
  .highlight.Socioeconomicstatus:not(.checked) {
      color: $Socioeconomicstatus;
      border-color: $Socioeconomicstatus;
  }
  .highlight.Health {
      background-color: $Health;
  }
  .highlight.Health:not(.checked) {
      color: $Health;
      border-color: $Health;
  }
  .highlight.Riskperception {
      background-color: $Riskperception;
  }
  .highlight.Riskperception:not(.checked) {
      color: $Riskperception;
      border-color: $Riskperception;
  }
  .highlight.Exposure {
      background-color: $Exposure;
  }
  .highlight.Exposure:not(.checked) {
      color: $Exposure;
      border-color: $Exposure;
  }
  #tooltip {
  position: absolute;
  opacity: 0;
  background: rgba(250, 250, 250, 0.93);
  padding: 2px;
 // border: 2px solid black;
  border-radius: 10px;
  pointer-events: none; /* Prevent tooltip from blocking mouse events */
}

  </style>