<template>
  <div class="plot_container" :class="{ plot_maximized: maximized, plot_minimized: !maximized }" ref="plot_container">
    <div class="plot" ref="plot_ref">
      <button class="plot_button" @click="plot_toggle_maximize">
        {{ maximized ? '-' : '+' }}
      </button>
    </div>
  </div>
</template>

<script setup>
import { defineProps, inject, onMounted, ref, useTemplateRef, watch } from 'vue'

const props = defineProps({ is_heatmap: Boolean, section: String, name: String })

const maximized = ref(false)

const plot_ref = useTemplateRef('plot_ref')
const plot_container = useTemplateRef('plot_container')

const plots = inject('plots')
const heatmaps = inject('heatmaps')
const params = inject('params')
const data = inject('data')

const plot_toggle_maximize = () => {
  maximized.value = !maximized.value
  Plotly.Plots.resize(plot_ref.value)
  document.body.style.overflow = maximized.value ? 'hidden' : 'visible'
}

const prevent_plotly_buttons_tab_focus = () => {
  const focusableElements = plot_container.value.querySelectorAll('a, button, input, select')
  focusableElements.forEach(elem => elem.setAttribute('tabindex', '-1'))
}

const heatmap_init = [{ colorscale: 'Electric', type: 'heatmap', x: [], y: [], z: [] }]

const plot_init = () => {
    const plot_config = plots.value[props.section][props.name]
    const plot_defs = { mode: 'lines', line: { width: 1 }, x: [], y: [] }

    switch (plot_config.type) {
    case 'lines':
      return Array.from(plot_config.cols, col => ({ ...plot_defs, name: col }))
    case 'stack':
      return Array.from(plot_config.cols, col => ({ ...plot_defs, stackgroup: 'sg', name: col }))
    case 'stack_percent':
      return Array.from(plot_config.cols, col => ({ ...plot_defs, stackgroup: 'sg', groupnorm: 'percent', name: col }))
    }
}

onMounted(() => {
  Plotly.newPlot(plot_ref.value, props.is_heatmap ? heatmap_init : plot_init(), {
    font: { color: 'gray', family: 'monospace' },
    legend: { maxheight: 100, orientation: 'h' },
    margin: { b: 48, l: 48, r: 48, t: 48 },
    paper_bgcolor: 'black',
    plot_bgcolor: 'black',
    title: { font: { size: 16 }, text: props.name, x: 0, xref: 'paper' },
    xaxis: { gridcolor: '#111', tickfont: { color: 'gray' }, zerolinecolor: 'gray' },
    yaxis: { gridcolor: '#111', tickfont: { color: 'gray' }, zerolinecolor: 'gray' },
  }, {
    displayModeBar: true,
    responsive: true,
  })

  prevent_plotly_buttons_tab_focus()
})

const update_plot = new_data => {
  const plot_config = plots.value[props.section][props.name]
  const cols = plot_config.cols
  const cols_count = cols.length
  const table_data = new_data.plot_values[plot_config.table]
  const traces = [...Array(cols_count).keys()]
  const xs = Array(cols_count).fill(table_data.map(elem => elem[params.value.axis]))
  const ys = cols.map(column => table_data.map(elem => elem[column]))

  // Clear traces
  if (new_data.redraw) {
    const restyle = {
      x: Array.from(cols, () => []),
      y: Array.from(cols, () => []),
    }

    Plotly.restyle(plot_ref.value, restyle)
  }

  Plotly.extendTraces(plot_ref.value, { x: xs, y: ys }, traces, params.value.rows)
}

const update_heatmap = new_data => {
  const heatmap_config = heatmaps.value[props.section][props.name]
  const table_data = new_data.heatmap_values[heatmap_config.table]
  const ys = [table_data.map(elem => elem[params.value.axis])]
  const zs = [table_data.map(elem => elem.eva_render.split(' ').map(str => Number('0x' + str)))]

  if (new_data.redraw) {
    const px_size = Math.pow(2, Number(params.value.pixel_pow))
    const restyle = {
      x: [Array.from(Array(Number(params.value.pixels)).keys()).map(i => Number(params.value.left) + i * px_size)],
      y: [[]],
      z: [[]],
    }

    Plotly.restyle(plot_ref.value, restyle)
  }

  Plotly.extendTraces(plot_ref.value, { y: ys, z: zs }, [0], params.value.rows)
}

watch(data, props.is_heatmap ? update_heatmap : update_plot)
</script>

<style>
.plot_container {
  background-color: black;
  display: inline-block;
  width: 100%;
}

.plot_maximized {
  height: 100%;
  left: 0;
  position: fixed;
  top: 0;
  z-index: 999;
}

.plot_minimized {
  height: 400px;
  position: relative;
  z-index: 0;
}

.plot_button {
  background-color: black;
  border: 1.5px solid gray;
  color: gray;
  cursor: pointer;
  font-family: monospace;
  font-size: 18px;
  height: 26px;
  padding: 0;
  position: absolute;
  right: 0;
  top: 0;
  width: 26px;
}

.plot {
  height: 100%;
}
</style>
