import { unsafeCSS, LitElement, html } from "lit";
import { property, state, query } from "lit/decorators.js";
import componentStyle from "./pie-chart.css.js";
import chartCommonStyle from "../../charthelpers/chart-common.css.js";
import chartDebugStyle from "../../charthelpers/chart-debug.css.js";
import chartLegendStyle from "../../charthelpers/chart-legend.css.js";
import { customElement } from "../../decorator.js";
import { Priority } from "../../navigation-instruments/types.js";
import { Chart, PieController, DoughnutController, ArcElement, Tooltip } from "chart.js";
import { CHART_DIMENSIONS, CHART_SECTOR_ENHANCED_COLORS, CHART_SECTOR_DEFAULT_COLORS, OUTER_LABEL_CONFIG } from "../../charthelpers/constants.js";
import { getChartColorsOrDefault, getCssVariableValue } from "../../charthelpers/colors.js";
import { observeThemeChanges } from "../../charthelpers/theme.js";
import { calculateSumTotal, createArcOuterLabelPlugin } from "../../charthelpers/outer-labels.js";
import { calculateFixedHeightChartLayout, formatNumericValue, formatSingleLabel } from "../../charthelpers/canvas-layout.js";
import { getChartTooltipOptions } from "../../charthelpers/tooltip.js";
import { generateLegendHTML } from "../../charthelpers/legend.js";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result) __defProp(target, key, result);
  return result;
};
Chart.register(PieController, DoughnutController, ArcElement, Tooltip);
const PIE_DIMENSIONS = {
  ...CHART_DIMENSIONS,
  GAP_AND_BORDER_COLOR: "--container-section-color"
};
const PIE_RECREATE_PROP_NAMES = [
  "priority",
  "sunburst",
  "showOuterLabels",
  "showUnit",
  "outerLabelUnit",
  "outerLabelMaxLength",
  "outerLabelDecimalPlaces",
  "showDebugOverlay",
  "fixedHeight"
];
const PIE_WATCHED_PROP_NAMES = [
  "legend",
  "data",
  "colors",
  "priority",
  "sunburst",
  "showOuterLabels",
  "showUnit",
  "outerLabelUnit",
  "outerLabelMaxLength",
  "outerLabelDecimalPlaces",
  "showDebugOverlay",
  "fixedHeight"
];
let ObcPieChart = class extends LitElement {
  constructor() {
    super(...arguments);
    this.data = [];
    this.colors = [];
    this.priority = Priority.regular;
    this.showOuterLabels = false;
    this.showUnit = false;
    this.sunburst = false;
    this.outerLabelUnit = "%";
    this.outerLabelMaxLength = 0;
    this.outerLabelDecimalPlaces = 0;
    this.legend = false;
    this.showDebugOverlay = false;
    this.fixedHeight = 320;
    this.total = 0;
    this.formattedLabels = [];
    this.activeSegmentIndex = null;
    this.wasAboveThreshold = false;
    this.handleCanvasClick = (event) => {
      if (!this.chart || !this.sunburst) return;
      const elements = this.chart.getElementsAtEventForMode(
        event,
        "nearest",
        { intersect: true },
        false
      );
      if (elements.length > 0) {
        const clickedIndex = elements[0].index;
        const newIndex = this.activeSegmentIndex === clickedIndex ? null : clickedIndex;
        this.activeSegmentIndex = newIndex;
        this.chart.destroy();
        this.createChart();
      }
    };
  }
  hasAnyChanged(changed, props) {
    return props.some((prop) => changed.has(prop));
  }
  /**
   * Get layout configuration for canvas calculation
   */
  getLayoutConfig() {
    return {
      unit: this.outerLabelUnit,
      showUnit: this.showUnit,
      outerLabelMaxLength: this.outerLabelMaxLength,
      decimalPlaces: this.outerLabelDecimalPlaces,
      data: this.data,
      denominator: this.total > 0 ? this.total : 1
    };
  }
  // Calculate derived state BEFORE render
  willUpdate(changed) {
    if (changed.has("data")) {
      this.total = calculateSumTotal(this.data);
    }
  }
  // Update external library AFTER render
  updated(changed) {
    super.updated(changed);
    if (this.hasAnyChanged(changed, PIE_WATCHED_PROP_NAMES)) {
      const needsRecreation = this.hasAnyChanged(
        changed,
        PIE_RECREATE_PROP_NAMES
      );
      if (needsRecreation) {
        this.chart?.destroy();
        this.removeSunburstInteraction();
        this.createChart();
        if (this.sunburst) {
          this.setupSunburstInteraction();
        }
      } else {
        this.updateChart();
      }
    }
  }
  firstUpdated() {
    this.createChart();
    this.themeObserver = observeThemeChanges(() => this.updateChartColors());
    this.setupResizeObserver();
    if (this.sunburst) {
      this.setupSunburstInteraction();
    }
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.chart?.destroy();
    this.themeObserver?.disconnect();
    this.resizeObserver?.disconnect();
    this.removeSunburstInteraction();
  }
  /**
   * Setup resize observer to detect when fixedHeight property changes programmatically
   * (e.g., via Storybook controls or user code)
   */
  setupResizeObserver() {
    if (!this.canvasEl) return;
    this.resizeObserver = new ResizeObserver(() => {
      if (!this.chart) return;
      const height2 = this.canvasEl?.clientHeight ?? 0;
      const isAboveThreshold = height2 >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;
      if (isAboveThreshold !== this.wasAboveThreshold) {
        this.wasAboveThreshold = isAboveThreshold;
        this.chart.destroy();
        this.createChart();
      } else {
        this.updateChart();
      }
    });
    this.resizeObserver.observe(this.canvasEl);
    const height = this.canvasEl.clientHeight;
    this.wasAboveThreshold = height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;
  }
  setupSunburstInteraction() {
    if (!this.canvasEl) return;
    this.canvasEl.addEventListener("click", this.handleCanvasClick);
    this.canvasEl.style.cursor = "pointer";
  }
  removeSunburstInteraction() {
    if (!this.canvasEl) return;
    this.canvasEl.removeEventListener("click", this.handleCanvasClick);
    this.canvasEl.style.cursor = "";
  }
  prepareChartData() {
    const values = this.data.map((d) => d.value);
    const labels = this.data.map((d) => d.label);
    const chartColors = getChartColorsOrDefault(
      this,
      this.colors,
      this.priority === Priority.enhanced ? CHART_SECTOR_ENHANCED_COLORS : CHART_SECTOR_DEFAULT_COLORS
    );
    const segmentColors = values.map(
      (_, index) => chartColors[index % chartColors.length]
    );
    if (!this.sunburst) {
      return {
        values,
        labels,
        colors: segmentColors,
        sunburstValues: [],
        sunburstColors: [],
        sunburstLabels: []
      };
    }
    const sunburstValues = [];
    const sunburstColors = [];
    const sunburstLabels = [];
    this.data.forEach((segment, parentIndex) => {
      const children = segment.children || [];
      if (children.length > 0) {
        children.forEach((child, childIndex) => {
          sunburstValues.push(child.value);
          sunburstLabels.push(child.label);
          const colorIndex = (parentIndex + childIndex + 1) % chartColors.length;
          sunburstColors.push(chartColors[colorIndex]);
        });
      } else {
        sunburstValues.push(segment.value);
        sunburstLabels.push("");
        sunburstColors.push("transparent");
      }
    });
    return {
      values,
      labels,
      colors: segmentColors,
      sunburstValues,
      sunburstColors,
      sunburstLabels
    };
  }
  /**
   * Get Chart.js options using centralized fixed height layout calculation
   */
  getChartOptions() {
    const radiusPercentage = this.sunburst && this.activeSegmentIndex !== null ? 75 : 100;
    const dimensions = calculateFixedHeightChartLayout({
      fixedHeight: this.fixedHeight,
      isHalfMode: false,
      // Pie charts are always full circles
      showOuterLabels: this.showOuterLabels,
      canvasEl: this.canvasEl,
      layoutConfig: this.getLayoutConfig(),
      host: this
    });
    this.formattedLabels = dimensions.formattedLabels;
    this.style.setProperty("--chart-width", `${dimensions.calculatedWidth}px`);
    this.style.setProperty("--chart-height", `${dimensions.actualHeight}px`);
    const dynamicPadding = dimensions.isTooSmall ? { top: 0, right: 0, bottom: 0, left: 0 } : {
      top: dimensions.topPadding,
      right: dimensions.rightPadding,
      bottom: dimensions.bottomPadding,
      left: dimensions.leftPadding
    };
    return {
      responsive: true,
      maintainAspectRatio: true,
      aspectRatio: dimensions.aspectRatio,
      radius: `${radiusPercentage}%`,
      layout: {
        padding: dynamicPadding ?? PIE_DIMENSIONS.CANVAS_PADDING
      },
      plugins: {
        legend: {
          display: false,
          labels: {
            generateLabels: () => []
            // Prevent Chart.js from generating labels internally
          },
          onClick: () => {
          }
          // Disable legend click handler
        },
        tooltip: {
          ...getChartTooltipOptions(this),
          enabled: !dimensions.isTooSmall,
          filter: (tooltipItem) => {
            const dataset = tooltipItem.dataset;
            const bgColor = Array.isArray(dataset.backgroundColor) ? dataset.backgroundColor[tooltipItem.dataIndex] : dataset.backgroundColor;
            return bgColor !== "transparent";
          },
          callbacks: {
            title: () => "",
            // No title line
            label: (context) => {
              const label = context.label ?? "";
              const value = context.parsed;
              const denominator = this.total > 0 ? this.total : 1;
              const isPercentage = this.outerLabelUnit === "%";
              const numericValue = formatNumericValue(
                value,
                denominator,
                isPercentage,
                this.outerLabelDecimalPlaces
              );
              const showUnit = this.showUnit && this.outerLabelUnit;
              return showUnit ? `${label} ${numericValue}${this.outerLabelUnit}` : `${label} ${numericValue}`;
            }
          }
        }
      },
      animation: {
        animateRotate: false,
        animateScale: false
      }
    };
  }
  createOuterLabelPiePlugin() {
    return createArcOuterLabelPlugin(this, {
      formattedLabels: this.formattedLabels,
      hideIndex: this.sunburst ? this.activeSegmentIndex : null
    });
  }
  createChart() {
    if (!this.canvasEl || !this.canvasEl.isConnected) return;
    const ctx = this.canvasEl.getContext("2d");
    if (!ctx) return;
    const {
      values,
      labels,
      colors,
      sunburstValues,
      sunburstColors,
      sunburstLabels
    } = this.prepareChartData();
    const datasets = [
      {
        data: values,
        backgroundColor: colors,
        borderWidth: 1,
        borderColor: getCssVariableValue(
          this,
          PIE_DIMENSIONS.GAP_AND_BORDER_COLOR
        )
      }
    ];
    const height = this.canvasEl?.clientHeight ?? 0;
    const isTooSmall = height < CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;
    this.chart = new Chart(ctx, {
      type: "pie",
      data: {
        labels,
        datasets
      },
      options: this.getChartOptions(),
      plugins: [
        // Only show outer labels if enabled AND height is large enough
        ...this.showOuterLabels && !isTooSmall ? [this.createOuterLabelPiePlugin()] : [],
        this.sunburst && sunburstValues.length > 0 ? this.createSunburstPlugin(
          sunburstValues,
          sunburstColors,
          sunburstLabels
        ) : { id: "sunburst" }
      ].filter((p) => p !== void 0)
    });
    requestAnimationFrame(() => this.updateLegend());
  }
  createSunburstPlugin(_outerValues, sunburstColors, sunburstLabels) {
    return {
      id: "sunburst",
      afterDatasetsDraw: (chart) => {
        const meta = chart.getDatasetMeta(0);
        if (!meta?.data.length) return;
        if (this.activeSegmentIndex === null) return;
        const { ctx } = chart;
        const centerX = chart.chartArea.left + chart.chartArea.width / 2;
        const centerY = chart.chartArea.top + chart.chartArea.height / 2;
        ctx.save();
        const firstArc = meta.data[0];
        const innerPieRadius = firstArc.outerRadius;
        const originalFullRadius = innerPieRadius / 0.75;
        const height = this.canvasEl?.clientHeight ?? 0;
        const isTooSmall = height < PIE_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;
        const gapWidth = isTooSmall ? 2 : 8;
        const outerRingInnerRadius = innerPieRadius + gapWidth;
        const outerRingOuterRadius = isTooSmall ? originalFullRadius : originalFullRadius;
        const fontFamily = getCssVariableValue(
          this,
          OUTER_LABEL_CONFIG.fontFamily
        );
        const fontWeight = getCssVariableValue(
          this,
          OUTER_LABEL_CONFIG.fontWeightVar
        );
        const fontSize = getCssVariableValue(
          this,
          OUTER_LABEL_CONFIG.fontSizeVar
        );
        const fontColor = getCssVariableValue(
          this,
          OUTER_LABEL_CONFIG.fontColorVar
        );
        ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`;
        ctx.fillStyle = fontColor;
        ctx.textBaseline = "middle";
        let sunburstDataIndex = 0;
        this.data.forEach((segment, segmentIndex) => {
          const children = segment.children || [];
          if (children.length > 0) {
            if (segmentIndex === this.activeSegmentIndex) {
              const childrenTotal = children.reduce(
                (sum, child) => sum + child.value,
                0
              );
              let startAngle = 0;
              const parentArc = meta.data[segmentIndex];
              const parentStart = parentArc.startAngle;
              const parentEnd = parentArc.endAngle;
              const parentAngleRange = parentEnd - parentStart;
              children.forEach((child) => {
                const childValue = child.value;
                const childRatio = childValue / childrenTotal;
                const childAngleRange = parentAngleRange * childRatio;
                const childStartAngle = parentStart + startAngle;
                const childEndAngle = childStartAngle + childAngleRange;
                ctx.fillStyle = sunburstColors[sunburstDataIndex] || "transparent";
                ctx.beginPath();
                ctx.arc(
                  centerX,
                  centerY,
                  outerRingOuterRadius,
                  childStartAngle,
                  childEndAngle
                );
                ctx.arc(
                  centerX,
                  centerY,
                  outerRingInnerRadius,
                  childEndAngle,
                  childStartAngle,
                  true
                );
                ctx.closePath();
                ctx.fill();
                if (this.showOuterLabels && sunburstLabels[sunburstDataIndex]) {
                  const middleAngle = (childStartAngle + childEndAngle) / 2;
                  const labelRadius = outerRingOuterRadius + OUTER_LABEL_CONFIG.labelGap;
                  const x = centerX + Math.cos(middleAngle) * labelRadius;
                  const y = centerY + Math.sin(middleAngle) * labelRadius;
                  const alignLeft = Math.cos(middleAngle) >= 0;
                  ctx.fillStyle = fontColor;
                  ctx.textAlign = alignLeft ? "left" : "right";
                  const textX = alignLeft ? x + OUTER_LABEL_CONFIG.labelGap : x - OUTER_LABEL_CONFIG.labelGap;
                  const total = this.total > 0 ? this.total : 1;
                  const valueText = formatSingleLabel(childValue, total, {
                    unit: this.outerLabelUnit,
                    showUnit: this.showUnit,
                    decimalPlaces: this.outerLabelDecimalPlaces,
                    maxLength: this.outerLabelMaxLength
                  });
                  ctx.fillText(valueText, textX, y);
                }
                startAngle += childAngleRange;
                sunburstDataIndex++;
              });
            } else {
              sunburstDataIndex += children.length;
            }
          } else {
            sunburstDataIndex++;
          }
        });
        ctx.restore();
      }
    };
  }
  updateChart() {
    if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;
    this.chart.update();
    requestAnimationFrame(() => this.updateLegend());
  }
  /**
   * Update only chart colors without recreating the entire chart
   * Used by theme observer for efficient theme changes
   */
  updateChartColors() {
    if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;
    const { colors, sunburstColors } = this.prepareChartData();
    if (this.chart.data.datasets[0]) {
      this.chart.data.datasets[0].backgroundColor = colors;
    }
    if (this.sunburst && this.chart.data.datasets[1]) {
      this.chart.data.datasets[1].backgroundColor = sunburstColors;
    }
    this.chart.update("none");
    requestAnimationFrame(() => this.updateLegend());
  }
  /**
   * Update the legend HTML content
   */
  updateLegend() {
    if (!this.legend || !this.legendDiv || !this.chart) return;
    const meta = this.chart.getDatasetMeta(0);
    if (!meta || !meta.controller) {
      return;
    }
    if (!this.data || this.data.length === 0) {
      this.legendDiv.innerHTML = "";
      return;
    }
    const denominator = this.total > 0 ? this.total : 1;
    const isPercentage = this.outerLabelUnit === "%";
    try {
      const legendItems = this.data.map((item, i) => {
        const style = meta.controller.getStyle(i, false);
        const numericValue = formatNumericValue(
          item.value,
          denominator,
          isPercentage,
          this.outerLabelDecimalPlaces
        );
        const showUnit = this.showUnit && this.outerLabelUnit;
        const value = `${numericValue}`;
        const unit = showUnit ? `${this.outerLabelUnit}` : "";
        return {
          fillStyle: style.backgroundColor,
          label: item.label,
          value,
          unit
        };
      });
      const legendHTML = generateLegendHTML(legendItems);
      this.legendDiv.innerHTML = legendHTML;
    } catch (error) {
      console.debug(
        "[obc-pie-chart] updateLegend: error generating legend HTML",
        error
      );
    }
  }
  render() {
    return html`
      <div class="wrapper">
        <canvas></canvas>
        ${this.legend ? html`<div class="legend"></div>` : ""}
      </div>
    `;
  }
};
ObcPieChart.styles = [
  unsafeCSS(componentStyle),
  unsafeCSS(chartCommonStyle),
  unsafeCSS(chartLegendStyle),
  unsafeCSS(chartDebugStyle)
];
__decorateClass([
  property({ attribute: false })
], ObcPieChart.prototype, "data", 2);
__decorateClass([
  property({ attribute: false })
], ObcPieChart.prototype, "colors", 2);
__decorateClass([
  property({ type: String })
], ObcPieChart.prototype, "priority", 2);
__decorateClass([
  property({ type: Boolean })
], ObcPieChart.prototype, "showOuterLabels", 2);
__decorateClass([
  property({ type: Boolean })
], ObcPieChart.prototype, "showUnit", 2);
__decorateClass([
  property({ type: Boolean })
], ObcPieChart.prototype, "sunburst", 2);
__decorateClass([
  property({ type: String })
], ObcPieChart.prototype, "outerLabelUnit", 2);
__decorateClass([
  property({
    type: Number
  })
], ObcPieChart.prototype, "outerLabelMaxLength", 2);
__decorateClass([
  property({
    type: Number
  })
], ObcPieChart.prototype, "outerLabelDecimalPlaces", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], ObcPieChart.prototype, "legend", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], ObcPieChart.prototype, "showDebugOverlay", 2);
__decorateClass([
  property({ type: Number, reflect: true })
], ObcPieChart.prototype, "fixedHeight", 2);
__decorateClass([
  state()
], ObcPieChart.prototype, "total", 2);
__decorateClass([
  state()
], ObcPieChart.prototype, "formattedLabels", 2);
__decorateClass([
  state()
], ObcPieChart.prototype, "activeSegmentIndex", 2);
__decorateClass([
  query("canvas")
], ObcPieChart.prototype, "canvasEl", 2);
__decorateClass([
  query(".legend")
], ObcPieChart.prototype, "legendDiv", 2);
ObcPieChart = __decorateClass([
  customElement("obc-pie-chart")
], ObcPieChart);
export {
  ObcPieChart
};
//# sourceMappingURL=pie-chart.js.map
