import { GaugeOptions } from '../models/options/gaugeOptions';
import { BarOptions } from '../models/options/barOptions';
import { Series } from '../models/series';
import { BarSeries } from '../models/barSeries';

import { PanelOptions, Pod } from '../types';
import { formatValue, getGrafanaSeriesList, getLastMetricValue } from '../utils';

import { ChartwerkGaugePod } from '@chartwerk/gauge-pod';
import { ChartwerkBarPod } from '@chartwerk/bar-pod';

import { PanelProps } from '@grafana/data';
import { VizLegend } from '@grafana/ui';
import { LegendDisplayMode } from '@grafana/schema';

import React, { useRef, useEffect, useMemo } from 'react';
import { css } from 'emotion';
import * as _ from 'lodash';

interface Props extends PanelProps<PanelOptions> {}

export function Panel({ options, data, width, height, timeRange, onChangeTimeRange, replaceVariables }: Props) {
  const grafanaSeriesList = useMemo(() => getGrafanaSeriesList(data, timeRange), [data, timeRange]);
  const podContainerRef = useRef<HTMLDivElement>(null);

  const podContainer = useMemo(() => {
    const chartClickHandler = (event: React.MouseEvent<HTMLDivElement>) => {
      event.preventDefault();
      if (options.gauge.link === undefined || options.gauge.link === '') {
        return;
      }
      const link = replaceVariables(options.gauge.link);
      window.open(link, '_self');
    };

    const isLinkActive = options.gauge.link !== undefined && options.gauge.link !== '';
    let containerHeight = height;
    if (options.visualizationType === Pod.BAR) {
      containerHeight = height - 20;
    }
    if (options.visualizationType === Pod.GAUGE && options.gauge.additionalInfo.display) {
      containerHeight = height - options.gauge.additionalInfo.size - 8;
    }

    return (
      <div
        ref={podContainerRef}
        className={css`
          width: ${width}px;
          height: ${containerHeight}px;
          cursor: ${isLinkActive ? 'pointer' : 'default'};
        `}
        onClick={chartClickHandler}
      ></div>
    );
  }, [width, height, options, replaceVariables]);

  useEffect(() => {
    let pod;
    if (podContainerRef.current === null) {
      return;
    }
    switch (options.visualizationType) {
      case Pod.GAUGE:
        const series = new Series(grafanaSeriesList, options.gauge.value).getChartwerkSeries();
        const chartwerkGaugeOptions = new GaugeOptions(grafanaSeriesList, options).getChartwerkOptions();
        pod = new ChartwerkGaugePod(podContainerRef.current, series, chartwerkGaugeOptions);
        break;
      case Pod.BAR:
        const barSeries = new BarSeries(grafanaSeriesList).getChartwerkSeries();
        const chartwerkBarOptions = new BarOptions(grafanaSeriesList, onChangeTimeRange).getChartwerkOptions();
        pod = new ChartwerkBarPod(podContainerRef.current, barSeries, chartwerkBarOptions);
        break;
      default:
        console.warn(`Unknown visualization type: ${options.visualizationType}`);
        return;
    }
    pod.render();
  }, [podContainer, grafanaSeriesList, onChangeTimeRange, options]);

  switch (options.visualizationType) {
    case Pod.GAUGE:
      let additionalInfo;
      const additionalInfoConfig = options.gauge.additionalInfo;
      if (additionalInfoConfig.display) {
        // TODO: move `useMetric` handling to utils, as it's duplicated in gaugeOptions.ts
        let value: number | undefined = undefined;
        if (!additionalInfoConfig.value?.useMetric) {
          value = additionalInfoConfig.value.value;
        } else {
          if (!_.isEmpty(additionalInfoConfig.value.metricName)) {
            const aggregatedValue = getLastMetricValue(
              grafanaSeriesList,
              additionalInfoConfig.value.metricName,
              'Additional Info'
            );
            value = aggregatedValue !== null ? aggregatedValue : undefined;
          }
        }

        additionalInfo = (
          <div
            className={css`
              width: ${width}px;
              height: ${additionalInfoConfig.size + 8}px;
              font-size: ${additionalInfoConfig.size}px;
              color: ${additionalInfoConfig.color};
              display: flex;
              justify-content: center;
              align-items: center;
            `}
          >
            {additionalInfoConfig.prefix} {value !== undefined ? formatValue(value, additionalInfoConfig) : '-'}
          </div>
        );
      }
      return (
        <div>
          {podContainer}
          {additionalInfo && additionalInfo}
        </div>
      );
    case Pod.BAR:
      const legendItems = _.map(grafanaSeriesList, (serie) => {
        return {
          label: serie.alias,
          color: serie.color,
          yAxis: 1,
        };
      });

      return (
        <div>
          {podContainer}

          <VizLegend placement={'bottom'} items={legendItems} displayMode={LegendDisplayMode.List} />
        </div>
      );
    default:
      console.warn(`Unknown visualization type: ${options.visualizationType}`);
      return <div>This visualization is not supported</div>;
  }
}
