<template>
  <div>
    <div class="panel">
      <div class="controls">
        <span class="label">Layout:</span>
        <button data-layout="classic" class="active">Classic raincloud</button>
        <button data-layout="cloud-rain">Cloud + rain</button>
        <button data-layout="cloud-box">Cloud + box</button>
        <button data-layout="overlay">Violin + box overlay</button>
      </div>
    </div>

    <div id="chart">
      <apexchart
        type="raincloud"
        height="420"
        :options="chartOptions"
        :series="series"
      ></apexchart>
    </div>

    <div class="panel">
      <div class="note">
        Every raincloud layer is its own switch on
        <code>plotOptions.violin</code>: <code>side</code> cuts the density to a
        half-violin, <code>box.show</code> toggles the five-number lane, and
        <code>points.position</code> moves the raw observations into their own
        lane or back under the density. A hidden layer hands its lane back to
        the cloud, so <b>Cloud + rain</b> and <b>Cloud + box</b> reflow instead
        of leaving a gap, and <b>Violin + box overlay</b> (<code
          >side: 'both'</code
        >) is the classic symmetric violin with the box drawn on its centerline.
      </div>
    </div>
  </div>
</template>

<script>
import VueApexCharts from 'vue-apexcharts'
import ApexCharts from 'apexcharts'

import 'apexcharts/features/raincloud'

// Raw observations per group (Box-Muller Gaussian; Math.random is seeded by
// the sample template).
function sample(mean, sd, n) {
  var points = []
  for (var k = 0; k < n; k++) {
    var u1 = Math.random(),
      u2 = Math.random()
    var g = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2)
    points.push(Math.round((mean + g * sd) * 10) / 10)
  }
  return points
}

// Each layout is a complete plotOptions.violin spec, so switching between
// them never leaves a leaf from the previous layout behind. Hidden layers
// hand their lane back to the cloud automatically.
var RAINCLOUD_LAYOUTS = {
  classic: {
    side: 'right',
    box: { show: true },
    points: { show: true, position: 'left' },
  },
  'cloud-rain': {
    side: 'right',
    box: { show: false },
    points: { show: true, position: 'left' },
  },
  'cloud-box': {
    side: 'right',
    box: { show: true },
    points: { show: false, position: 'left' },
  },
  overlay: {
    side: 'both',
    box: { show: true },
    points: { show: true, position: 'center', constrainToViolin: true },
  },
}

export default {
components: {
apexchart: VueApexCharts,
},
data: function () {
return {
series: [
  {
    name: 'Measurement',
    data: [
      { x: 'North', points: sample(52, 9, 160) },
      { x: 'East', points: sample(61, 6, 160) },
      { x: 'South', points: sample(47, 12, 160) },
    ],
  },
],
chartOptions: {
chart: {
  id: 'raincloudVariations',
  type: 'raincloud',
  height: 420,
},
colors: ['#14b8a6'],
title: {
  text: 'One distribution chart, four layouts',
  align: 'left',
},
yaxis: {
  title: {
    text: 'Measurement',
  },
},
},
raincloudTimer: null,
}
},
mounted: function () {
  // The vue-apexcharts wrapper owns the render, so reach the live instance
  // by its chart.id, then wire the same controls the vanilla build does.
  // (RAINCLOUD_LAYOUTS lives in the shared head script.)
  var me = this
  me.raincloudTimer = window.setInterval(function () {
    var chart = ApexCharts.getChartByID('raincloudVariations')
    if (!chart) return
    window.clearInterval(me.raincloudTimer)

    var buttons = Array.prototype.slice.call(
      document.querySelectorAll('.controls button[data-layout]')
    )
    buttons.forEach(function (btn) {
      btn.addEventListener('click', function () {
        buttons.forEach(function (b) { b.classList.remove('active') })
        btn.classList.add('active')
        chart.updateOptions({
          plotOptions: { violin: RAINCLOUD_LAYOUTS[btn.getAttribute('data-layout')] },
        })
      })
    })
  }, 50)
},
beforeDestroy: function () {
  window.clearInterval(this.raincloudTimer)
},,
}
</script>

<style>
#chart {
  max-width: 820px;
  margin: 12px auto 4px;
}
.panel {
  max-width: 820px;
  margin: 14px auto;
  font-family: sans-serif;
}
.controls {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.controls .label {
  font-size: 13px;
  color: #556;
  margin-right: 2px;
}
.controls button {
  padding: 6px 12px;
  cursor: pointer;
  border: 1px solid #d3d8e3;
  background: #fff;
  border-radius: 6px;
  font-size: 13px;
}
.controls button.active {
  border-color: #14b8a6;
  color: #0f766e;
  background: #f0fdfa;
  font-weight: 600;
}
.note {
  background: #f0fdfa;
  border-left: 3px solid #14b8a6;
  padding: 11px 15px;
  font-size: 13px;
  color: #234;
  border-radius: 2px;
  line-height: 1.6;
}
.note code {
  background: #c7f0ea;
  padding: 1px 5px;
  border-radius: 3px;
}
</style>