/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 {ECPolygon} from '../line/poly';
import * as graphic from '../../util/graphic';
import { setStatesStylesFromModel, enableHoverEmphasis } from '../../util/states';
import {setLabelStyle, getLabelStatesModels} from '../../label/labelStyle';
import {bind} from 'zrender/src/core/util';
import DataDiffer from '../../data/DataDiffer';
import ChartView from '../../view/Chart';
import ThemeRiverSeriesModel from './ThemeRiverSeries';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import { RectLike } from 'zrender/src/core/BoundingRect';
import { ColorString } from '../../util/types';

type LayerSeries = ReturnType<ThemeRiverSeriesModel['getLayerSeries']>;

class ThemeRiverView extends ChartView {

    static readonly type = 'themeRiver';
    readonly type = ThemeRiverView.type;

    private _layersSeries: LayerSeries;
    private _layers: graphic.Group[] = [];

    render(seriesModel: ThemeRiverSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
        const data = seriesModel.getData();
        const self = this;

        const group = this.group;

        const layersSeries = seriesModel.getLayerSeries();

        const layoutInfo = data.getLayout('layoutInfo');
        const rect = layoutInfo.rect;
        const boundaryGap = layoutInfo.boundaryGap;

        group.x = 0;
        group.y = rect.y + boundaryGap[0];

        function keyGetter(item: LayerSeries[number]) {
            return item.name;
        }
        const dataDiffer = new DataDiffer(
            this._layersSeries || [], layersSeries,
            keyGetter, keyGetter
        );

        const newLayersGroups: graphic.Group[] = [];

        dataDiffer
            .add(bind(process, this, 'add'))
            .update(bind(process, this, 'update'))
            .remove(bind(process, this, 'remove'))
            .execute();

        function process(status: 'add' | 'update' | 'remove', idx: number, oldIdx?: number) {
            const oldLayersGroups = self._layers;
            if (status === 'remove') {
                group.remove(oldLayersGroups[idx]);
                return;
            }
            const points0: number[] = [];
            const points1: number[] = [];
            let style;
            const indices = layersSeries[idx].indices;
            let j = 0;
            for (; j < indices.length; j++) {
                const layout = data.getItemLayout(indices[j]);
                const x = layout.x;
                const y0 = layout.y0;
                const y = layout.y;

                points0.push(x, y0);
                points1.push(x, y0 + y);

                style = data.getItemVisual(indices[j], 'style');
            }

            let polygon: ECPolygon;
            const textLayout = data.getItemLayout(indices[0]);
            const labelModel = seriesModel.getModel('label');
            const margin = labelModel.get('margin');
            const emphasisModel = seriesModel.getModel('emphasis');

            if (status === 'add') {
                const layerGroup = newLayersGroups[idx] = new graphic.Group();
                polygon = new ECPolygon({
                    shape: {
                        points: points0,
                        stackedOnPoints: points1,
                        smooth: 0.4,
                        stackedOnSmooth: 0.4,
                        smoothConstraint: false
                    },
                    z2: 0
                });
                layerGroup.add(polygon);
                group.add(layerGroup);

                if (seriesModel.isAnimationEnabled()) {
                    polygon.setClipPath(createGridClipShape(polygon.getBoundingRect(), seriesModel, function () {
                        polygon.removeClipPath();
                    }));
                }
            }
            else {
                const layerGroup = oldLayersGroups[oldIdx];
                polygon = layerGroup.childAt(0) as ECPolygon;
                group.add(layerGroup);

                newLayersGroups[idx] = layerGroup;

                graphic.updateProps(polygon, {
                    shape: {
                        points: points0,
                        stackedOnPoints: points1
                    }
                }, seriesModel);
            }

            setLabelStyle(polygon, getLabelStatesModels(seriesModel), {
                labelDataIndex: indices[j - 1],
                defaultText: data.getName(indices[j - 1]),
                inheritColor: style.fill as ColorString
            }, {
                normal: {
                    verticalAlign: 'middle'
                    // align: 'right'
                }
            });
            polygon.setTextConfig({
                position: null,
                local: true
            });

            const labelEl = polygon.getTextContent();
            // TODO More label position options.
            if (labelEl) {
                labelEl.x = textLayout.x - margin;
                labelEl.y = textLayout.y0 + textLayout.y / 2;
            }

            polygon.useStyle(style);

            data.setItemGraphicEl(idx, polygon);

            setStatesStylesFromModel(polygon, seriesModel);
            enableHoverEmphasis(polygon, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
        }

        this._layersSeries = layersSeries;
        this._layers = newLayersGroups;
    }
};

// add animation to the view
function createGridClipShape(rect: RectLike, seriesModel: ThemeRiverSeriesModel, cb: () => void) {
    const rectEl = new graphic.Rect({
        shape: {
            x: rect.x - 10,
            y: rect.y - 10,
            width: 0,
            height: rect.height + 20
        }
    });
    graphic.initProps(rectEl, {
        shape: {
            x: rect.x - 50,
            width: rect.width + 100,
            height: rect.height + 20
        }
    }, seriesModel, cb);

    return rectEl;
}

export default ThemeRiverView;