import React from 'react'
import ReactApexChart from 'react-apexcharts'
import ApexCharts from 'apexcharts'
import './styles.css'

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 },
  },
}

const ApexChart = () => {
  const [state, setState] = React.useState({
    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) },
        ],
      },
    ],
    options: {
      chart: {
        id: 'raincloudVariations',
        type: 'raincloud',
        height: 420,
      },
      colors: ['#14b8a6'],
      title: {
        text: 'One distribution chart, four layouts',
        align: 'left',
      },
      yaxis: {
        title: {
          text: 'Measurement',
        },
      },
    },
  })

  React.useEffect(() => {
    // The react-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.)
    let chart
    const timer = window.setInterval(() => {
      chart = ApexCharts.getChartByID('raincloudVariations')
      if (!chart) return
      window.clearInterval(timer)

      const buttons = Array.prototype.slice.call(
        document.querySelectorAll('.controls button[data-layout]'),
      )
      buttons.forEach((btn) => {
        btn.addEventListener('click', () => {
          buttons.forEach((b) => b.classList.remove('active'))
          btn.classList.add('active')
          chart.updateOptions({
            plotOptions: {
              violin: RAINCLOUD_LAYOUTS[btn.getAttribute('data-layout')],
            },
          })
        })
      })
    }, 50)

    return () => window.clearInterval(timer)
  }, [])

  return (
    <div>
      <div className="panel">
        <div className="controls">
          <span className="label">Layout:</span>
          <button data-layout="classic" className="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">
        <ReactApexChart
          options={state.options}
          series={state.series}
          type="raincloud"
          height={420}
        />
      </div>

      <div className="panel">
        <div className="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>
  )
}

export default ApexChart