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

// Perspectives (#10): capture the full VIEW state (zoom window, hidden series,
// selection, theme, annotations) as a token, apply it back, or encode it into
// a shareable URL. Passive: no config flag needed.
function bigSeries(seed, amp) {
  var d = []
  var v = seed
  for (var i = 0; i < 40; i++) {
    v += (Math.random() - 0.5) * amp
    d.push({ x: i + 1, y: Math.round(v) })
  }
  return d
}

const ApexChart = () => {
  const [state, setState] = React.useState({
    series: [
      { name: 'North', data: bigSeries(50, 14) },
      { name: 'South', data: bigSeries(70, 10) },
    ],
    options: {
      chart: {
        height: 380,
        type: 'line',
        id: 'perspectives-demo',
        animations: { enabled: true },
        toolbar: {
          show: true,
          tools: { zoom: true, pan: true, reset: true, download: false },
        },
        zoom: { enabled: true, type: 'x' },
        ink: { enabled: true },
        contextMenu: { enabled: true },
      },
      colors: ['#1971c2', '#e0447e'],
      stroke: { curve: 'smooth', width: 2 },
      dataLabels: { enabled: false },
      title: {
        text: 'Capture, apply, and share the exact view',
        align: 'left',
      },
      xaxis: { type: 'numeric', title: { text: 'Step' } },
      legend: { position: 'top' },
    },
  })

  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.
    // (bigSeries lives in the shared head script.) Perspectives drives the chart
    // instance directly, so no React state changes and the chart is never
    // re-rendered under it.
    let chart
    const timer = window.setInterval(() => {
      chart = ApexCharts.getChartByID('perspectives-demo')
      if (!chart) return
      window.clearInterval(timer)

      const viewsSel = document.getElementById('views')
      const linkEl = document.getElementById('link')
      let saveCount = 0

      function refreshList() {
        const list = chart.perspectives.list()
        viewsSel.innerHTML =
          '<option value="">' +
          (list.length ? 'Pick a saved view...' : '(none yet)') +
          '</option>'
        list.forEach(function (p) {
          const o = document.createElement('option')
          o.value = p.id
          o.textContent = p.name
          viewsSel.appendChild(o)
        })
      }

      document.getElementById('save').addEventListener('click', function () {
        saveCount++
        chart.perspectives.save('View ' + saveCount)
        refreshList()
      })

      viewsSel.addEventListener('change', function () {
        const id = viewsSel.value
        if (!id) return
        const entry = chart.perspectives.list().filter(function (p) {
          return p.id === id
        })[0]
        if (entry) chart.perspectives.apply(entry.token, { animate: true })
      })

      document.getElementById('copy').addEventListener('click', function () {
        const url = chart.perspectives.toURL()
        linkEl.textContent = url
        if (navigator.clipboard)
          navigator.clipboard.writeText(url).catch(function () {})
      })

      document
        .getElementById('resetZoom')
        .addEventListener('click', function () {
          chart.resetSeries(true, true)
        })

      // Restore a shared view if the page was opened with a #apex= fragment.
      try {
        const shared =
          ApexCharts.perspectives && ApexCharts.perspectives.fromURL()
        if (shared) chart.perspectives.apply(shared, { animate: false })
      } catch (e) {}
    }, 50)

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

  return (
    <div>
      <div className="panel">
        <div className="controls">
          <button id="save" className="primary">
            Save current view
          </button>
          <label>
            Saved:
            <select id="views">
              <option value="">(none yet)</option>
            </select>
          </label>
          <button id="copy">Copy shareable link</button>
          <button id="resetZoom">Reset zoom</button>
        </div>
        <div className="link" id="link"></div>
      </div>

      <div id="chart">
        <ReactApexChart
          options={state.options}
          series={state.series}
          type="line"
          height={380}
        />
      </div>

      <div className="panel">
        <div className="note">
          Zoom into a region (drag on the plot), hide a series in the legend, or
          right-click the plot to drop a note or a dashed line (
          <code>chart.contextMenu</code> + <code>chart.ink</code>), then press
          Save current view: <code>chart.perspectives.capture()</code> plus
          <code>save(name)</code> stores it. Annotations are part of the view,
          so a saved or shared view brings your notes and lines back, still
          draggable and editable. Pick a saved view to <code>apply()</code> it
          back (the chart animates to that exact state). Copy shareable link
          uses
          <code>chart.perspectives.toURL()</code> to encode the view into a
          <code>#apex=</code> fragment; opening that link restores it on load
          via
          <code>ApexCharts.perspectives.fromURL()</code>.
        </div>
      </div>
    </div>
  )
}

export default ApexChart
Shareable Views (Perspectives) - React Narrative & State | ApexCharts.js | ApexCharts.js