/**
 * Datart
 *
 * Copyright 2021
 *
 * 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 { ChartDataSectionType } from 'app/constants';
import Chart from 'app/models/Chart';
import { ChartDrillOption } from 'app/models/ChartDrillOption';
import { ChartSelectionManager } from 'app/models/ChartSelectionManager';
import {
  ChartConfig,
  ChartDataSectionField,
  ChartStyleConfig,
  SelectedItem,
} from 'app/types/ChartConfig';
import ChartDataSetDTO from 'app/types/ChartDataSet';
import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker';
import {
  getDrillableRows,
  getStyles,
  transformToDataSet
} from 'app/utils/chartHelper';
import Config from './config';

import VChart from '@visactor/vchart';
import type { ISpec } from '@visactor/vchart/esm/typings';

class BasicVisPieChart extends Chart {
  config = Config;
  chart: any = null;
  selectionManager?: ChartSelectionManager;

  protected isCircle = false;
  protected isRose = false;

  constructor(props?) {
    super(
      props?.id || 'pie',
      props?.name || 'viz.palette.graph.names.pieChart',
      props?.icon || 'chartpie',
    );
    this.meta.requirements = props?.requirements || [
      { group: [0, 1], aggregate: [1, 999] },
    ];
  }

  onMount(options: BrokerOption, context: BrokerContext) {
    if (
      options.containerId === undefined ||
      !context.document ||
      !context.window
    ) {
      return;
    }


    // @ts-ignore
    const spec = this.getVChartSpec(options.containerId,options.dataset, options.config, options.drillOption, options.selectedItems);
    this.chart = new VChart(spec,{dom:context.document.getElementById(options.containerId)!});
    //this.selectionManager = new ChartSelectionManager(this.mouseEvents);
    //this.selectionManager.attachWindowListeners(context.window);
    this.chart?.renderSync();
  }

  onUpdated(options: BrokerOption, context: BrokerContext) {
    if (!options.dataset || !options.dataset.columns || !options.config) {
      return;
    }
    if (!this.isMatchRequirement(options.config)) {
      // 清空当前实例，会移除实例中所有的组件和图表。
      this.chart?.release();
      return;
    }
    this.selectionManager?.updateSelectedItems(options?.selectedItems);

    const data = this.getVChartData(
      options.dataset,
      options.config,
      options.drillOption
    )
    const spec = this.getVChartSpec(options.containerId,options.dataset, options.config, options.drillOption, options.selectedItems);
    this.chart?.updateSpec(spec);
  }

  onUnMount(options: BrokerOption, context: BrokerContext) {
    this.selectionManager?.removeWindowListeners(context.window);
    this.selectionManager?.removeZRenderListeners(this.chart);
    this.chart?.release();
  }

  onResize(options: BrokerOption, context: BrokerContext) {
    //this.chart?.resize(context);
  }


  private getVChartData(
    dataset: ChartDataSetDTO,
    config: ChartConfig,
    drillOption?: ChartDrillOption,
  ){
    const dataConfigs = config.datas || [];
    const groupConfigs: ChartDataSectionField[] = getDrillableRows(
      dataConfigs,
      drillOption,
    );
    const aggregateConfigs = dataConfigs
      .filter(c => c.type === ChartDataSectionType.Aggregate)
      .flatMap(config => config.rows || []);
    const infoConfigs = dataConfigs
      .filter(c => c.type === ChartDataSectionType.Info)
      .flatMap(config => config.rows || []);
    const chartDataSet = transformToDataSet(
      dataset.rows,
      dataset.columns,
      dataConfigs,
    );

    return chartDataSet?.map((row) => {
      return {
        type: groupConfigs.map(row.getCell, row).join('-'),
        value: aggregateConfigs.concat(infoConfigs).map(row.getCell, row),
      };
    });
  }


  private getVChartSpec(
    containerId: string|number,
    dataset: ChartDataSetDTO,
    config: ChartConfig,
    drillOption?: ChartDrillOption,
    selectedItems?: SelectedItem[],
  ):ISpec {
    console.log("dataset--->",dataset)
    console.log("config--->",config)


    const styleConfigs = config.styles || [];
    const dataConfigs = config.datas || [];
    const groupConfigs: ChartDataSectionField[] = getDrillableRows(
      dataConfigs,
      drillOption,
    );
    const aggregateConfigs = dataConfigs
      .filter(c => c.type === ChartDataSectionType.Aggregate)
      .flatMap(config => config.rows || []);
    const infoConfigs = dataConfigs
      .filter(c => c.type === ChartDataSectionType.Info)
      .flatMap(config => config.rows || []);

    const chartDataSet = transformToDataSet(
      dataset.rows,
      dataset.columns,
      dataConfigs,
    );

    const values = chartDataSet?.map((row) => {
      return {
        type: groupConfigs.map(row.getCell, row).join('-'),
        value: aggregateConfigs.concat(infoConfigs).map(row.getCell, row),
      };
    });

    const legends = this.getLegends(styleConfigs)

    return  {
      type: 'pie',
      outerRadius: 0.8,
      valueField: 'value',
      categoryField: 'type',
      legends,
      label: {
        visible: true
      },
      tooltip: {
        mark: {
          content: [
            {
              key: datum => datum?.['type'],
              value: datum => datum?.['value'] + '%'
            }
          ]
        }
      },
      data: [
        {
          id:containerId,
          values
        }
      ]
    };
  }

  private getLegends(
    styles: ChartStyleConfig[],
  ){
    const [show, type, font, legendPos, selectAll, height] = getStyles(
      styles,
      ['legend'],
      ['showLegend', 'type', 'font', 'position', 'selectAll', 'height'],
    );

    return {
      visible:show,
      orient:legendPos
    };
  }




}

export default BasicVisPieChart;
