/*
* 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 {createSymbol, normalizeSymbolOffset, normalizeSymbolSize} from '../../util/symbol';
import {Group, Path} from '../../util/graphic';
import { enterEmphasis, leaveEmphasis, toggleHoverEmphasis } from '../../util/states';
import SymbolClz from './Symbol';
import SeriesData from '../../data/SeriesData';
import type { ZRColor, ECElement } from '../../util/types';
import type Displayable from 'zrender/src/graphic/Displayable';
import { SymbolDrawItemModelOption } from './SymbolDraw';

interface RippleEffectCfg {
    showEffectOn?: 'emphasis' | 'render'
    rippleScale?: number
    brushType?: 'fill' | 'stroke'
    period?: number
    effectOffset?: number
    z?: number
    zlevel?: number
    symbolType?: string
    color?: ZRColor
    rippleEffectColor?: ZRColor,
    rippleNumber?: number
}

function updateRipplePath(rippleGroup: Group, effectCfg: RippleEffectCfg) {
    const color = effectCfg.rippleEffectColor || effectCfg.color;
    rippleGroup.eachChild(function (ripplePath: Displayable) {
        ripplePath.attr({
            z: effectCfg.z,
            zlevel: effectCfg.zlevel,
            style: {
                stroke: effectCfg.brushType === 'stroke' ? color : null,
                fill: effectCfg.brushType === 'fill' ? color : null
            }
        });
    });
}

class EffectSymbol extends Group {

    private _effectCfg: RippleEffectCfg;

    constructor(data: SeriesData, idx: number) {
        super();

        const symbol = new SymbolClz(data, idx);
        const rippleGroup = new Group();
        this.add(symbol);
        this.add(rippleGroup);

        this.updateData(data, idx);
    }


    stopEffectAnimation() {
        (this.childAt(1) as Group).removeAll();
    }

    startEffectAnimation(effectCfg: RippleEffectCfg) {
        const symbolType = effectCfg.symbolType;
        const color = effectCfg.color;
        const rippleNumber = effectCfg.rippleNumber;
        const rippleGroup = this.childAt(1) as Group;

        for (let i = 0; i < rippleNumber; i++) {
            // If width/height are set too small (e.g., set to 1) on ios10
            // and macOS Sierra, a circle stroke become a rect, no matter what
            // the scale is set. So we set width/height as 2. See #4136.
            const ripplePath = createSymbol(
                symbolType, -1, -1, 2, 2, color
            );
            ripplePath.attr({
                style: {
                    strokeNoScale: true
                },
                z2: 99,
                silent: true,
                scaleX: 0.5,
                scaleY: 0.5
            });

            const delay = -i / rippleNumber * effectCfg.period + effectCfg.effectOffset;
            ripplePath.animate('', true)
                .when(effectCfg.period, {
                    scaleX: effectCfg.rippleScale / 2,
                    scaleY: effectCfg.rippleScale / 2
                })
                .delay(delay)
                .start();
            ripplePath.animateStyle(true)
                .when(effectCfg.period, {
                    opacity: 0
                })
                .delay(delay)
                .start();

            rippleGroup.add(ripplePath);
        }

        updateRipplePath(rippleGroup, effectCfg);
    }

    /**
     * Update effect symbol
     */
    updateEffectAnimation(effectCfg: RippleEffectCfg) {
        const oldEffectCfg = this._effectCfg;
        const rippleGroup = this.childAt(1) as Group;

        // Must reinitialize effect if following configuration changed
        const DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale', 'rippleNumber'] as const;
        for (let i = 0; i < DIFFICULT_PROPS.length; i++) {
            const propName = DIFFICULT_PROPS[i];
            if (oldEffectCfg[propName] !== effectCfg[propName]) {
                this.stopEffectAnimation();
                this.startEffectAnimation(effectCfg);
                return;
            }
        }

        updateRipplePath(rippleGroup, effectCfg);
    }

    /**
     * Highlight symbol
     */
    highlight() {
        enterEmphasis(this);
    }

    /**
     * Downplay symbol
     */
    downplay() {
        leaveEmphasis(this);
    }

    getSymbolType() {
        const symbol = this.childAt(0) as SymbolClz;
        return symbol && symbol.getSymbolType();
    }

    /**
     * Update symbol properties
     */
    updateData(data: SeriesData, idx: number) {
        const seriesModel = data.hostModel;

        (this.childAt(0) as SymbolClz).updateData(data, idx);

        const rippleGroup = this.childAt(1);
        const itemModel = data.getItemModel<SymbolDrawItemModelOption>(idx);
        const symbolType = data.getItemVisual(idx, 'symbol');
        const symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));

        const symbolStyle = data.getItemVisual(idx, 'style');
        const color = symbolStyle && symbolStyle.fill;
        const emphasisModel = itemModel.getModel('emphasis');

        rippleGroup.setScale(symbolSize);

        rippleGroup.traverse(function (ripplePath: Path) {
            ripplePath.setStyle('fill', color);
        });

        const symbolOffset = normalizeSymbolOffset(data.getItemVisual(idx, 'symbolOffset'), symbolSize);
        if (symbolOffset) {
            rippleGroup.x = symbolOffset[0];
            rippleGroup.y = symbolOffset[1];
        }

        const symbolRotate = data.getItemVisual(idx, 'symbolRotate');
        rippleGroup.rotation = (symbolRotate || 0) * Math.PI / 180 || 0;

        const effectCfg: RippleEffectCfg = {};

        effectCfg.showEffectOn = seriesModel.get('showEffectOn');
        effectCfg.rippleScale = itemModel.get(['rippleEffect', 'scale']);
        effectCfg.brushType = itemModel.get(['rippleEffect', 'brushType']);
        effectCfg.period = itemModel.get(['rippleEffect', 'period']) * 1000;
        effectCfg.effectOffset = idx / data.count();
        effectCfg.z = seriesModel.getShallow('z') || 0;
        effectCfg.zlevel = seriesModel.getShallow('zlevel') || 0;
        effectCfg.symbolType = symbolType;
        effectCfg.color = color;
        effectCfg.rippleEffectColor = itemModel.get(['rippleEffect', 'color']);
        effectCfg.rippleNumber = itemModel.get(['rippleEffect', 'number']);

        if (effectCfg.showEffectOn === 'render') {
            this._effectCfg
                ? this.updateEffectAnimation(effectCfg)
                : this.startEffectAnimation(effectCfg);

            this._effectCfg = effectCfg;
        }
        else {
            // Not keep old effect config
            this._effectCfg = null;

            this.stopEffectAnimation();

            (this as ECElement).onHoverStateChange = (toState) => {
                if (toState === 'emphasis') {
                    if (effectCfg.showEffectOn !== 'render') {
                        this.startEffectAnimation(effectCfg);
                    }
                }
                else if (toState === 'normal') {
                    if (effectCfg.showEffectOn !== 'render') {
                        this.stopEffectAnimation();
                    }
                }
            };
        }

        this._effectCfg = effectCfg;

        toggleHoverEmphasis(
            this,
            emphasisModel.get('focus'),
            emphasisModel.get('blurScope'),
            emphasisModel.get('disabled')
        );
    };

    fadeOut(cb: () => void) {
        cb && cb();
    };

}

export default EffectSymbol;
