<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>
      <div id="legend-container"></div>
      <div id="text2" class="text-container">
      <p><em>Many social vulnerability determinants have been studied. Some show positive relationships with water insecurity, some with negative, and others inconclusive (Drakes et al. 2024). Interact with the chart to see the level of agreement across studies.</em></p>
    </div>
    </section>
  </template>
  
  <script setup>
  import { onMounted, ref } 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"
  };

  const patternId = 'pattern-stripe';

  // bar chart patterning and fills
  const legendData = [
  { name: 'Positive', color: dimensionColors['Demographiccharacteristics'] },
  { name: 'Negative', color: 'white', stroke: dimensionColors['Demographiccharacteristics'] },
  { name: 'Unknown', pattern: true, color: `url(#pattern-stripe)`, stroke: dimensionColors['Demographiccharacteristics'] }
];

function createLegend() {
  const legend = d3.select('#legend-container')
    .append('svg')
    .attr('width', width)
    .attr('height', 50)
    .attr('class', 'legend');

  const legendGroup = legend.selectAll('g')
    .data(legendData)
    .enter()
    .append('g')
    .attr('transform', (d, i) => `translate(${i * 100}, 0)`);

  legendGroup.append('rect')
    .attr('x', 15)
    .attr('y', 17)
    .attr('width', 15)
    .attr('height', 15)
    .attr('class', d => d.name.toLowerCase() + '-key')
    .style('fill', d => d.pattern ? d.color : d.color)
    .style('stroke', d => d.stroke ? d.stroke : 'none')
    .style('stroke-width', d => d.stroke ? 2 : 0);

  legendGroup.append('text')
    .attr('x', 35)
    .attr('y', 25)
    .attr('dy', '0.35em')
    //.style('font-size', '12px')
    .text(d => d.name);
    
}
  
  // 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("Consensus");

    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', handleMouseOver)
    .on('mouseout', handleMouseOut);
  
    // 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))); });
      }

      createLegend(); // add legend to caption
  }
  
  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');

  // Set the y scale
  const yScale = d3.scaleLinear()
    .domain([40, d3.max(data.value, d => d.level_agreement)])
    .range([height - margin.bottom, margin.top]);

  // Set the radius scale 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]);
  console.log('Active categories:', activeCategories);

  // Select all bubbles and bind data
  const bubbles = svg.selectAll(".bubble")
    .data(data.value, d => d.id);

  // Update existing bubbles
  bubbles
    .attr('r', d => radiusScale(d.evidence_val))
    .style('fill', d => activeCategories.includes(d.dimension.replace(' ', '')) ? dimensionColors[d.dimension.replace(' ', '')] : 'rgba(217, 217, 217, 0.95)');

  // Add new bubbles
  bubbles.enter()
    .append('circle')
    .attr('class', 'bubble')
    .attr('r', d => radiusScale(d.evidence_val))
    .style('fill', d => activeCategories.includes(d.dimension.replace(' ', '')) ? dimensionColors[d.dimension.replace(' ', '')] : 'rgba(217, 217, 217, 0.95)')
    .attr('cx', d => d.x)  // Use existing x position
    .attr('cy', d => d.y)
    .on('mouseover', handleMouseOver)
    .on('mouseout', handleMouseOut)
    .merge(bubbles);

  // Ensure all bubbles are handled correctly
  bubbles.exit().remove();
}

//tooltip
function handleMouseOver(event, d) {

  const activeCategories = Object.keys(isChecked.value).filter(category => isChecked.value[category]);

  // Check if the category of the data point is toggled
  if (!activeCategories.includes(d.dimension.replace(' ', ''))) {
    return;  // Do nothing if the category is untoggled
  }

  const [x, y] = d3.pointer(event, svg.node());
  const tooltip = d3.select('#tooltip');

  tooltip.html('')
    .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: `url(#pattern-stripe)` }
  ];

  // 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') 
    .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
    .attr('stroke-width', 3); 

  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(#${patternId})` : d.fill)
    .style('stroke', d => d.stroke ? d.stroke : 'none');

  // Position the tooltip
  tooltip
    .style('opacity', 1)
    .style('left', (x + 10) + 'px')
    .style('top', (y - 28) + 'px');

  // Highlight the circle
  d3.select(this)
    .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
    .attr('stroke-width', 8);

    d3.select('#legend-container').select('.positive-key')
    .style('fill', dimensionColors[d.dimension.replace(' ', '')]);

    d3.select('#legend-container').select('.negative-key')
    .style('stroke', dimensionColors[d.dimension.replace(' ', '')]);

  d3.select('#legend-container').select('.unknown-key')
    //.select('path')
    .style('stroke', dimensionColors[d.dimension.replace(' ', '')]);

    // Show the legend
 // d3.select('#legend-container').style('display', 'block');
}

function handleMouseOut() {
  d3.select('#tooltip').style('opacity', 0);
  d3.select(this)
    .attr('stroke', null)
    .attr('stroke-width', null);

    // Hide the legend
  //d3.select('#legend-container').style('display', 'none');
}


  </script>
  
<style scoped lang="scss">
$switchWidth: 12rem;
$Demographiccharacteristics: #092836;
$Landtenure: #1b695e;
$Livingconditions: #7a5195;
$Socioeconomicstatus: #2a468f;
$Health: #ef5675;
$Riskperception: #ff764a;
$Exposure: #ffa600;
$ThemeGrey: rgba(217, 217, 217, 0.95);

#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;
}

.yLabel {
    font-weight: bold;
}

.highlight {
  color: white;
  padding: 0.25px 5px;
  border-radius: 10px;
  white-space: nowrap;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.1s;

  &.Demographiccharacteristics {
    background-color: $Demographiccharacteristics;
  }

  &.Landtenure {
    background-color: $Landtenure;
  }

  &.Livingconditions {
    background-color: $Livingconditions;
  }

  &.Socioeconomicstatus {
    background-color: $Socioeconomicstatus;
  }

  &.Health {
    background-color: $Health;
  }

  &.Riskperception {
    background-color: $Riskperception;
  }

  &.Exposure {
    background-color: $Exposure;
  }

  &:not(.checked) {
    color: black;
    background-color: $ThemeGrey;
  }
}

#tooltip {
  position: absolute;
  opacity: 0;
  background:  $ThemeGrey;
  padding: 2px;
 // border: 2px solid black;
  border-radius: 10px;
  pointer-events: none; /* Prevent tooltip from blocking mouse events */
}
.hidden {
  display: none;
}

#legend-container {
  display: none; /* Hide the legend initially */
}
#caption-container {
  margin-top: 20px;
  font-style: italic;
  margin-left: auto;
  margin-right: auto;
}
  </style>