/*
* 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';
import { saveOldStyle } from '../../animation/basicTrasition';

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);

                saveOldStyle(polygon);
            }

            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;