/*
* 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 { AnimationEasing } from 'zrender/src/animation/easing';
import Element from 'zrender/src/Element';
import { keys, filter, each, isArray, indexOf } from 'zrender/src/core/util';
import { ELEMENT_ANIMATABLE_PROPS } from './customGraphicTransition';
import { AnimationOption, AnimationOptionMixin, Dictionary } from '../util/types';
import { Model } from '../echarts.all';
import { getAnimationConfig } from './basicTransition';
import { warn } from '../util/log';
import { makeInner } from '../util/model';

// Helpers for creating keyframe based animations in custom series and graphic components.

type AnimationKeyframe<T extends Record<string, any>> = T & {
    easing?: AnimationEasing
    percent?: number    // 0 - 1
};

type StateToRestore = Dictionary<any>;
const getStateToRestore = makeInner<StateToRestore, Element>();

const KEYFRAME_EXCLUDE_KEYS = ['percent', 'easing', 'shape', 'style', 'extra'] as const;

export interface ElementKeyframeAnimationOption<Props extends Record<string, any>> extends AnimationOption {
    // Animation configuration for keyframe based animation.
    loop?: boolean
    keyframes?: AnimationKeyframe<Props>[]
}

/**
 * Stop previous keyframe animation and restore the attributes.
 * Avoid new keyframe animation starts with wrong internal state when the percent: 0 is not set.
 */
export function stopPreviousKeyframeAnimationAndRestore(el: Element) {
    // Stop previous keyframe animation.
    el.stopAnimation('keyframe');
    // Restore
    el.attr(getStateToRestore(el));
}

export function applyKeyframeAnimation<T extends Record<string, any>>(
    el: Element,
    animationOpts: ElementKeyframeAnimationOption<T> | ElementKeyframeAnimationOption<T>[],
    animatableModel: Model<AnimationOptionMixin>
) {
    if (!animatableModel.isAnimationEnabled() || !animationOpts) {
        return;
    }

    if (isArray(animationOpts)) {
        each(animationOpts, singleAnimationOpts => {
            applyKeyframeAnimation(el, singleAnimationOpts, animatableModel);
        });
        return;
    }

    const keyframes = animationOpts.keyframes;
    let duration = animationOpts.duration;

    if (animatableModel && duration == null) {
        // Default to use duration of config.
        // NOTE: animation config from payload will be ignored because they are mainly for transitions.
        const config = getAnimationConfig('enter', animatableModel, 0);
        duration = config && config.duration;
    }

    if (!keyframes || !duration) {
        return;
    }

    const stateToRestore: StateToRestore = getStateToRestore(el);

    each(ELEMENT_ANIMATABLE_PROPS, (targetPropName) => {
        if (targetPropName && !(el as any)[targetPropName]) {
            return;
        }

        let animator: ReturnType<Element['animate']>;
        let endFrameIsSet = false;

        // Sort keyframes by percent.
        keyframes.sort((a, b) => a.percent - b.percent);

        each(keyframes, kf => {
            // Stop current animation.
            const animators = el.animators;
            const kfValues = targetPropName ? kf[targetPropName] : kf;

            if (__DEV__) {
                if (kf.percent >= 1) {
                    endFrameIsSet = true;
                }
            }

            if (!kfValues) {
                return;
            }

            let propKeys = keys(kfValues);
            if (!targetPropName) {
                // PENDING performance?
                propKeys = filter(propKeys, key => indexOf(KEYFRAME_EXCLUDE_KEYS, key) < 0);
            }
            if (!propKeys.length) {
                return;
            }

            if (!animator) {
                animator = el.animate(targetPropName, animationOpts.loop, true);
                animator.scope = 'keyframe';
            }
            for (let i = 0; i < animators.length; i++) {
                // Stop all other animation that is not keyframe.
                if (animators[i] !== animator && animators[i].targetName === animator.targetName) {
                    animators[i].stopTracks(propKeys);
                }
            }

            targetPropName && (stateToRestore[targetPropName] = stateToRestore[targetPropName] || {});

            const savedTarget = targetPropName ? stateToRestore[targetPropName] : stateToRestore;
            each(propKeys, key => {
                // Save original value.
                savedTarget[key] = ((targetPropName ? (el as any)[targetPropName] : el) || {})[key];
            });

            animator.whenWithKeys(duration * kf.percent, kfValues, propKeys, kf.easing);
        });
        if (!animator) {
            return;
        }

        if (__DEV__) {
            if (!endFrameIsSet) {
                warn('End frame with percent: 1 is missing in the keyframeAnimation.', true);
            }
        }

        animator
            .delay(animationOpts.delay || 0)
            .duration(duration)
            .start(animationOpts.easing);
    });
}