// Copyright (C) 2026 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import m from 'mithril';
import type {EChartsCoreOption} from 'echarts/core';
import {formatNumber} from './chart_utils';
import {
  EChartView,
  type EChartEventHandler,
  type EChartClickParams,
} from './echart_view';
import {buildLegendOption, buildTooltipOption} from './chart_option_builder';
import type {LegendPosition} from './common';

/**
 * A single slice in the pie chart.
 */
export interface PieChartSlice {
  /** Label for this slice */
  readonly label: string;
  /** Numeric value for this slice */
  readonly value: number;
  /** Optional custom color for this slice */
  readonly color?: string;
}

/**
 * Data provided to a PieChart.
 */
export interface PieChartData {
  /** The slices to display */
  readonly slices: readonly PieChartSlice[];
}

export interface PieChartAttrs {
  /**
   * Pie chart data to display, or undefined if loading.
   * When undefined, a loading spinner is shown.
   */
  readonly data: PieChartData | undefined;

  /**
   * Height of the chart in pixels. Defaults to 200.
   */
  readonly height?: number;

  /**
   * Fill parent container. Defaults to false.
   */
  readonly fillParent?: boolean;

  /**
   * Custom class name for the container.
   */
  readonly className?: string;

  /**
   * Format function for values in tooltips.
   */
  readonly formatValue?: (value: number) => string;

  /**
   * Show legend. Defaults to true.
   */
  readonly showLegend?: boolean;

  /**
   * Where the legend sits relative to the chart. Defaults to 'right'.
   */
  readonly legendPosition?: LegendPosition;

  /**
   * Show percentage labels on slices. Defaults to false.
   */
  readonly showLabels?: boolean;

  /**
   * Inner radius ratio for donut chart (0-1). 0 = pie, >0 = donut.
   * Defaults to 0 (pie chart).
   */
  readonly innerRadiusRatio?: number;

  /**
   * Callback when a slice is clicked.
   */
  readonly onSliceClick?: (slice: PieChartSlice) => void;
}

export class PieChart implements m.ClassComponent<PieChartAttrs> {
  view({attrs}: m.Vnode<PieChartAttrs>) {
    const {data, height, fillParent, className} = attrs;

    const validSlices = data?.slices.filter((s) => s.value > 0) ?? [];
    const isEmpty = data !== undefined && validSlices.length === 0;
    const option =
      validSlices.length > 0 ? buildPieOption(attrs, validSlices) : undefined;

    return m(EChartView, {
      option,
      height,
      fillParent,
      className,
      empty: isEmpty,
      eventHandlers: buildPieEventHandlers(attrs, validSlices),
    });
  }
}

function buildPieOption(
  attrs: PieChartAttrs,
  slices: readonly PieChartSlice[],
): EChartsCoreOption {
  const {
    formatValue = (v: number) => formatNumber(v),
    showLegend = true,
    legendPosition = 'right',
    showLabels = false,
    innerRadiusRatio = 0,
  } = attrs;
  const legendOnRight = showLegend && legendPosition === 'right';

  const pieData = slices.map((s) => ({
    name: s.label,
    value: s.value,
    itemStyle: s.color !== undefined ? {color: s.color} : undefined,
  }));

  const outerPct = legendOnRight ? 65 : 75;
  const outerRadius = `${outerPct}%`;
  const innerRadius = `${Math.round(outerPct * innerRadiusRatio)}%`;

  return {
    animation: false,
    tooltip: buildTooltipOption({
      trigger: 'item' as const,
      formatter: (params: {
        name?: string;
        value?: number;
        percent?: number;
      }) => {
        const name = params.name ?? '';
        const value = params.value ?? 0;
        const pct = params.percent?.toFixed(1) ?? '0';
        return [name, `Value: ${formatValue(value)}`, `${pct}%`].join('<br>');
      },
    }),
    legend: showLegend ? buildLegendOption(legendPosition) : {show: false},
    series: [
      {
        type: 'pie',
        radius: [innerRadius, outerRadius],
        center: legendOnRight ? ['35%', '50%'] : ['50%', '50%'],
        data: pieData,
        label: {
          show: showLabels,
          formatter: '{d}%',
          fontSize: 10,
        },
        emphasis: {
          scaleSize: 5,
        },
        itemStyle: {
          borderWidth: 2,
        },
      },
    ],
  };
}

function buildPieEventHandlers(
  attrs: PieChartAttrs,
  slices: readonly PieChartSlice[],
): ReadonlyArray<EChartEventHandler> {
  if (!attrs.onSliceClick || slices.length === 0) return [];
  const onSliceClick = attrs.onSliceClick;
  return [
    {
      eventName: 'click',
      handler: (params) => {
        const p = params as EChartClickParams;
        const idx = p.dataIndex;
        if (idx !== undefined && idx >= 0 && idx < slices.length) {
          onSliceClick(slices[idx]);
        }
      },
    },
  ];
}
