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

import 'apexcharts/features/trellis'

// Six locations, each a real heatmap of day x hour check-ins, all six drawn
// against ONE colour scale derived from the union of every panel's values.
// That is the whole point of the grid: the same fill means the same count
// everywhere, so the quiet sites read as quiet. Six independently shaded
// heatmaps would give every panel its own darkest cell and the comparison
// would be a lie.
//
// Deterministic counts so the e2e snapshot is stable.
function mulberry32(seed) {
  return function () {
    seed |= 0
    seed = (seed + 0x6d2b79f5) | 0
    var t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296
  }
}

var DAYS = ['Sun', 'Sat', 'Fri', 'Thu', 'Wed', 'Tue', 'Mon']
var HOURS = ['6a', '8a', '10a', '12p', '2p', '4p', '6p', '8p']

// Each location has its own rhythm AND its own overall volume: the commuter
// sites are busiest, the campus site is a midday hump, the lakeside site is
// small and evening-heavy. Volume differences are the point of one scale.
var LOCATIONS = [
  {
    name: 'Central Station',
    seed: 7,
    volume: 1.0,
    peaks: [1, 6],
    weekend: 0.45,
  },
  { name: 'Harbor Point', seed: 19, volume: 0.82, peaks: [1, 6], weekend: 0.6 },
  {
    name: 'University Campus',
    seed: 31,
    volume: 0.66,
    peaks: [3, 4],
    weekend: 0.3,
  },
  {
    name: 'Riverside Mall',
    seed: 43,
    volume: 0.58,
    peaks: [4, 5],
    weekend: 1.15,
  },
  {
    name: 'Airport North',
    seed: 59,
    volume: 0.74,
    peaks: [0, 7],
    weekend: 0.95,
  },
  {
    name: 'Lakeside Park',
    seed: 71,
    volume: 0.31,
    peaks: [5, 6],
    weekend: 1.4,
  },
]

function hourlyRow(rand, loc, dayIndex) {
  // DAYS runs Sun..Mon top to bottom, so weekend factor keys off the ends.
  var isWeekend = dayIndex === 0 || dayIndex === 1
  var dayFactor = isWeekend ? loc.weekend : 0.85 + rand() * 0.3
  return HOURS.map(function (hour, hi) {
    var near = Math.min(
      Math.abs(hi - loc.peaks[0]),
      Math.abs(hi - loc.peaks[1]),
    )
    var shape = Math.max(0.12, 1 - near * 0.28)
    var v = 130 * loc.volume * dayFactor * shape * (0.85 + rand() * 0.3)
    return { x: hour, y: Math.round(v) }
  })
}

var activitySeries = []
LOCATIONS.forEach(function (loc) {
  var rand = mulberry32(loc.seed)
  DAYS.forEach(function (day, di) {
    activitySeries.push({
      name: day,
      location: loc.name,
      data: hourlyRow(rand, loc, di),
    })
  })
})

const ApexChart = () => {
  const [state, setState] = React.useState({
    series: activitySeries,
    options: {
      chart: {
        id: 'activityTrellis',
        type: 'heatmap',
        height: 620,
        animations: {
          enabled: false,
        },
      },
      trellis: {
        by: 'location',
        columns: 3,
        minPanelWidth: 300,
        gap: 14,
      },
      colors: ['#0E7490'],
      plotOptions: {
        heatmap: {
          radius: 2,
          enableShades: true,
          shadeIntensity: 0.55,
          colorScale: {
            gradientLegend: {
              formatter: function (val) {
                return Math.round(Number(val)) + ' check-ins'
              },
            },
          },
        },
      },
      dataLabels: {
        enabled: false,
      },
      stroke: {
        width: 1,
        colors: ['#fff'],
      },
      xaxis: {
        type: 'category',
      },
      tooltip: {
        compact: true,
        y: {
          formatter: function (val) {
            return val + ' check-ins'
          },
        },
      },
    },
  })

  return (
    <div>
      <div className="wrap">
        <h1>When each location is actually busy</h1>
        <p className="lead">
          Six day-by-hour heatmaps under one colour scale and one gradient
          legend. The commuter double-peak, the campus midday hump and the
          weekend-shaped park all read at a glance, and so does the plain fact
          that the park is a fraction of the size of the station.
        </p>

        <div className="chart-wrap">
          <div id="chart">
            <ReactApexChart
              options={state.options}
              series={state.series}
              type="heatmap"
              height={620}
            />
          </div>
        </div>

        <div className="note">
          The trellis derives the colour domain over the union of all panels and
          pushes an absolute <code>colorScale.min</code>/<code>max</code> into
          every one, so a given count lands on exactly the same fill in every
          panel. The grid then draws ONE gradient strip for the whole thing
          instead of six identical legends, and hovering a cell traces the same
          value in every other panel. Asking for{' '}
          <code>scales.color: 'independent'</code> is refused with a warning:
          per-panel shading is the classic way a heatmap grid misleads. The cell
          tooltip is one line (<code>tooltip.compact</code>), because a full
          card would cover the row it is captioning. Trellis is a premium
          feature; without a license it renders with a trial watermark.
        </div>
      </div>
    </div>
  )
}

export default ApexChart