<script lang="ts" setup>
import type {
  ChartInterface,
  DataByColumns,
  Settings,
} from '@milaboratories/miplots4';
import { PlAlert } from '@platforma-sdk/ui-vue';
import {
  computed,
  onBeforeUnmount,
  shallowRef,
  useCssModule,
  useTemplateRef,
  watchEffect,
} from 'vue';
import { residueColors } from './colors';
import { cellSize } from './cell-size';
import type { ResidueCounts } from './types';
import { useMiPlots } from './useMiPlots';

const props = defineProps<{
  residueCounts: ResidueCounts;
  width?: number;
  height?: number;
}>();

const classes = useCssModule();

const plotEl = useTemplateRef('plotEl');

const settings = computed(() => ({
  type: 'discrete',
  title: {
    name: '',
    show: false,
  },
  size: {
    width: props.width ?? props.residueCounts.length * cellSize.inline,
    height: props.height ?? 80,
    innerOffset: 0,
    outerOffset: 0,
  },
  frame: {
    type: 'empty',
  },
  xAxis: {
    title: '',
    showGrid: false,
    showTicks: false,
    hiddenLabels: true,
  },
  yAxis: {
    title: '',
    showGrid: false,
    showTicks: false,
    hiddenLabels: true,
  },
  y: {
    type: 'column',
    value: 'countKey',
  },
  primaryGrouping: {
    columnName: {
      type: 'column',
      value: 'columnKey',
    },
    unlimitedGroupsCount: true,
  },
  secondaryGrouping: {
    columnName: {
      type: 'column',
      value: 'residueKey',
    },
    unlimitedGroupsCount: true,
  },
  layers: [{
    type: 'logo',
    aes: { fillColor: residueColors },
  }],
} satisfies Settings));

const data = computed<DataByColumns>(() => {
  const countKey: number[] = [];
  const columnKey: number[] = [];
  const residueKey: string[] = [];
  for (const [columnIndex, column] of props.residueCounts.entries()) {
    for (const [residue, count] of Object.entries(column)) {
      if (residue === '-') continue;
      countKey.push(count);
      columnKey.push(columnIndex);
      residueKey.push(residue);
    }
  }
  return ({
    type: 'columns',
    id: `seq-logo-${crypto.randomUUID()}`,
    values: { countKey, columnKey, residueKey },
  });
});

const { miplots, error } = useMiPlots();

const plot = shallowRef<ChartInterface>();

watchEffect(async () => {
  if (!plotEl.value || !miplots.value) return;
  if (!plot.value) {
    plot.value = miplots.value.newPlot(data.value, settings.value);
    plot.value.mount(plotEl.value);
  } else {
    plot.value.updateSettingsAndData(data.value, settings.value);
  }
});

onBeforeUnmount(() => {
  plot.value?.unmount();
});
</script>

<template>
  <PlAlert v-if="error" type="error">
    {{ error.message }}
  </PlAlert>
  <div v-else ref="plotEl" :class="classes.container" />
</template>

<style module>
.container {
  svg {
    display: block;
  }
}
</style>
