/*
* 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.
*/

// TODO: move labels out of viewport.

import {
    Text as ZRText,
    BoundingRect,
    Polyline,
    updateProps,
    initProps,
    isElementRemoved
} from '../util/graphic';
import { getECData } from '../util/innerStore';
import ExtensionAPI from '../core/ExtensionAPI';
import {
    ZRTextAlign,
    ZRTextVerticalAlign,
    LabelLayoutOption,
    LabelLayoutOptionCallback,
    LabelLayoutOptionCallbackParams,
    LabelLineOption,
    Dictionary,
    ECElement,
    SeriesDataType
} from '../util/types';
import { parsePercent } from '../util/number';
import ChartView from '../view/Chart';
import Element, { ElementTextConfig } from 'zrender/src/Element';
import { RectLike } from 'zrender/src/core/BoundingRect';
import Transformable from 'zrender/src/core/Transformable';
import { updateLabelLinePoints, setLabelLineStyle, getLabelLineStatesModels } from './labelGuideHelper';
import SeriesModel from '../model/Series';
import { makeInner } from '../util/model';
import { retrieve2, each, keys, isFunction, filter, indexOf } from 'zrender/src/core/util';
import { PathStyleProps } from 'zrender/src/graphic/Path';
import Model from '../model/Model';
import { prepareLayoutList, hideOverlap, shiftLayoutOnX, shiftLayoutOnY } from './labelLayoutHelper';
import { labelInner, animateLabelValue } from './labelStyle';

interface LabelDesc {
    label: ZRText
    labelLine: Polyline

    seriesModel: SeriesModel
    // Can be null if label doesn't represent any data.
    dataIndex?: number
    // Can be null if label doesn't represent any data.
    dataType?: SeriesDataType

    layoutOption: LabelLayoutOptionCallback | LabelLayoutOption
    computedLayoutOption: LabelLayoutOption

    hostRect: RectLike
    rect: RectLike

    priority: number

    defaultAttr: SavedLabelAttr
}

interface SavedLabelAttr {
    ignore: boolean
    labelGuideIgnore: boolean

    x: number
    y: number
    scaleX: number
    scaleY: number
    rotation: number

    style: {
        align: ZRTextAlign
        verticalAlign: ZRTextVerticalAlign
        width: number
        height: number
        fontSize: number | string

        x: number
        y: number
    }

    cursor: string

    // Configuration in attached element
    attachedPos: ElementTextConfig['position']
    attachedRot: ElementTextConfig['rotation']

}

function cloneArr(points: number[][]) {
    if (points) {
        const newPoints = [];
        for (let i = 0; i < points.length; i++) {
            newPoints.push(points[i].slice());
        }
        return newPoints;
    }
}

function prepareLayoutCallbackParams(labelItem: LabelDesc, hostEl?: Element): LabelLayoutOptionCallbackParams {
    const label = labelItem.label;
    const labelLine = hostEl && hostEl.getTextGuideLine();
    return {
        dataIndex: labelItem.dataIndex,
        dataType: labelItem.dataType,
        seriesIndex: labelItem.seriesModel.seriesIndex,
        text: labelItem.label.style.text,
        rect: labelItem.hostRect,
        labelRect: labelItem.rect,
        // x: labelAttr.x,
        // y: labelAttr.y,
        align: label.style.align,
        verticalAlign: label.style.verticalAlign,
        labelLinePoints: cloneArr(labelLine && labelLine.shape.points)
    };
}

const LABEL_OPTION_TO_STYLE_KEYS = ['align', 'verticalAlign', 'width', 'height', 'fontSize'] as const;

const dummyTransformable = new Transformable();

const labelLayoutInnerStore = makeInner<{
    oldLayout: {
        x: number,
        y: number,
        rotation: number
    },
    oldLayoutSelect?: {
        x?: number,
        y?: number,
        rotation?: number
    },
    oldLayoutEmphasis?: {
        x?: number,
        y?: number,
        rotation?: number
    },

    needsUpdateLabelLine?: boolean
}, ZRText>();

const labelLineAnimationStore = makeInner<{
    oldLayout: {
        points: number[][]
    }
}, Polyline>();

type LabelLineOptionMixin = {
    labelLine: LabelLineOption,
    emphasis: { labelLine: LabelLineOption }
};

function extendWithKeys(target: Dictionary<any>, source: Dictionary<any>, keys: string[]) {
    for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        if (source[key] != null) {
            target[key] = source[key];
        }
    }
}

const LABEL_LAYOUT_PROPS = ['x', 'y', 'rotation'];

class LabelManager {

    private _labelList: LabelDesc[] = [];
    private _chartViewList: ChartView[] = [];

    constructor() {}

    clearLabels() {
        this._labelList = [];
        this._chartViewList = [];
    }

    /**
     * Add label to manager
     */
    private _addLabel(
        dataIndex: number | null | undefined,
        dataType: SeriesDataType | null | undefined,
        seriesModel: SeriesModel,
        label: ZRText,
        layoutOption: LabelDesc['layoutOption']
    ) {
        const labelStyle = label.style;
        const hostEl = label.__hostTarget;
        const textConfig = hostEl.textConfig || {};

        // TODO: If label is in other state.
        const labelTransform = label.getComputedTransform();
        const labelRect = label.getBoundingRect().plain();
        BoundingRect.applyTransform(labelRect, labelRect, labelTransform);

        if (labelTransform) {
            dummyTransformable.setLocalTransform(labelTransform);
        }
        else {
            // Identity transform.
            dummyTransformable.x = dummyTransformable.y = dummyTransformable.rotation =
                dummyTransformable.originX = dummyTransformable.originY = 0;
            dummyTransformable.scaleX = dummyTransformable.scaleY = 1;
        }

        const host = label.__hostTarget;
        let hostRect;
        if (host) {
            hostRect = host.getBoundingRect().plain();
            const transform = host.getComputedTransform();
            BoundingRect.applyTransform(hostRect, hostRect, transform);
        }

        const labelGuide = hostRect && host.getTextGuideLine();

        this._labelList.push({
            label,
            labelLine: labelGuide,

            seriesModel,
            dataIndex,
            dataType,

            layoutOption,
            computedLayoutOption: null,

            rect: labelRect,

            hostRect,

            // Label with lower priority will be hidden when overlapped
            // Use rect size as default priority
            priority: hostRect ? hostRect.width * hostRect.height : 0,

            // Save default label attributes.
            // For restore if developers want get back to default value in callback.
            defaultAttr: {
                ignore: label.ignore,
                labelGuideIgnore: labelGuide && labelGuide.ignore,

                x: dummyTransformable.x,
                y: dummyTransformable.y,
                scaleX: dummyTransformable.scaleX,
                scaleY: dummyTransformable.scaleY,
                rotation: dummyTransformable.rotation,

                style: {
                    x: labelStyle.x,
                    y: labelStyle.y,

                    align: labelStyle.align,
                    verticalAlign: labelStyle.verticalAlign,
                    width: labelStyle.width,
                    height: labelStyle.height,

                    fontSize: labelStyle.fontSize
                },

                cursor: label.cursor,

                attachedPos: textConfig.position,
                attachedRot: textConfig.rotation
            }
        });
    }

    addLabelsOfSeries(chartView: ChartView) {
        this._chartViewList.push(chartView);

        const seriesModel = chartView.__model;

        const layoutOption = seriesModel.get('labelLayout');

        /**
         * Ignore layouting if it's not specified anything.
         */
        if (!(isFunction(layoutOption) || keys(layoutOption).length)) {
            return;
        }

        chartView.group.traverse((child) => {
            if (child.ignore) {
                return true;    // Stop traverse descendants.
            }

            // Only support label being hosted on graphic elements.
            const textEl = child.getTextContent();
            const ecData = getECData(child);
            // Can only attach the text on the element with dataIndex
            if (textEl && !(textEl as ECElement).disableLabelLayout) {
                this._addLabel(ecData.dataIndex, ecData.dataType, seriesModel, textEl, layoutOption);
            }
        });
    }

    updateLayoutConfig(api: ExtensionAPI) {
        const width = api.getWidth();
        const height = api.getHeight();

        function createDragHandler(el: Element, labelLineModel: Model) {
            return function () {
                updateLabelLinePoints(el, labelLineModel);
            };
        }
        for (let i = 0; i < this._labelList.length; i++) {
            const labelItem = this._labelList[i];
            const label = labelItem.label;
            const hostEl = label.__hostTarget;
            const defaultLabelAttr = labelItem.defaultAttr;
            let layoutOption;
            // TODO A global layout option?
            if (isFunction(labelItem.layoutOption)) {
                layoutOption = labelItem.layoutOption(
                    prepareLayoutCallbackParams(labelItem, hostEl)
                );
            }
            else {
                layoutOption = labelItem.layoutOption;
            }

            layoutOption = layoutOption || {};
            labelItem.computedLayoutOption = layoutOption;

            const degreeToRadian = Math.PI / 180;
            // TODO hostEl should always exists.
            // Or label should not have parent because the x, y is all in global space.
            if (hostEl) {
                hostEl.setTextConfig({
                    // Force to set local false.
                    local: false,
                    // Ignore position and rotation config on the host el if x or y is changed.
                    position: (layoutOption.x != null || layoutOption.y != null)
                        ? null : defaultLabelAttr.attachedPos,
                    // Ignore rotation config on the host el if rotation is changed.
                    rotation: layoutOption.rotate != null
                        ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.attachedRot,
                    offset: [layoutOption.dx || 0, layoutOption.dy || 0]
                });
            }
            let needsUpdateLabelLine = false;
            if (layoutOption.x != null) {
                // TODO width of chart view.
                label.x = parsePercent(layoutOption.x, width);
                label.setStyle('x', 0);  // Ignore movement in style. TODO: origin.
                needsUpdateLabelLine = true;
            }
            else {
                label.x = defaultLabelAttr.x;
                label.setStyle('x', defaultLabelAttr.style.x);
            }

            if (layoutOption.y != null) {
                // TODO height of chart view.
                label.y = parsePercent(layoutOption.y, height);
                label.setStyle('y', 0);  // Ignore movement in style.
                needsUpdateLabelLine = true;
            }
            else {
                label.y = defaultLabelAttr.y;
                label.setStyle('y', defaultLabelAttr.style.y);
            }

            if (layoutOption.labelLinePoints) {
                const guideLine = hostEl.getTextGuideLine();
                if (guideLine) {
                    guideLine.setShape({ points: layoutOption.labelLinePoints });
                    // Not update
                    needsUpdateLabelLine = false;
                }
            }

            const labelLayoutStore = labelLayoutInnerStore(label);
            labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine;

            label.rotation = layoutOption.rotate != null
                ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation;

            label.scaleX = defaultLabelAttr.scaleX;
            label.scaleY = defaultLabelAttr.scaleY;

            for (let k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) {
                const key = LABEL_OPTION_TO_STYLE_KEYS[k];
                label.setStyle(key, layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]);
            }


            if (layoutOption.draggable) {
                label.draggable = true;
                label.cursor = 'move';
                if (hostEl) {
                    let hostModel: Model<LabelLineOptionMixin> =
                        labelItem.seriesModel as SeriesModel<LabelLineOptionMixin>;
                    if (labelItem.dataIndex != null) {
                        const data = labelItem.seriesModel.getData(labelItem.dataType);
                        hostModel = data.getItemModel<LabelLineOptionMixin>(labelItem.dataIndex);
                    }
                    label.on('drag', createDragHandler(hostEl, hostModel.getModel('labelLine')));
                }
            }
            else {
                // TODO Other drag functions?
                label.off('drag');
                label.cursor = defaultLabelAttr.cursor;
            }
        }
    }

    layout(api: ExtensionAPI) {
        const width = api.getWidth();
        const height = api.getHeight();

        const labelList = prepareLayoutList(this._labelList);
        const labelsNeedsAdjustOnX = filter(labelList, function (item) {
            return item.layoutOption.moveOverlap === 'shiftX';
        });
        const labelsNeedsAdjustOnY = filter(labelList, function (item) {
            return item.layoutOption.moveOverlap === 'shiftY';
        });

        shiftLayoutOnX(labelsNeedsAdjustOnX, 0, width);
        shiftLayoutOnY(labelsNeedsAdjustOnY, 0, height);

        const labelsNeedsHideOverlap = filter(labelList, function (item) {
            return item.layoutOption.hideOverlap;
        });

        hideOverlap(labelsNeedsHideOverlap);
    }

    /**
     * Process all labels. Not only labels with layoutOption.
     */
    processLabelsOverall() {
        each(this._chartViewList, (chartView) => {
            const seriesModel = chartView.__model;
            const ignoreLabelLineUpdate = chartView.ignoreLabelLineUpdate;
            const animationEnabled = seriesModel.isAnimationEnabled();

            chartView.group.traverse((child) => {
                if (child.ignore && !(child as ECElement).forceLabelAnimation) {
                    return true;    // Stop traverse descendants.
                }

                let needsUpdateLabelLine = !ignoreLabelLineUpdate;
                const label = child.getTextContent();
                if (!needsUpdateLabelLine && label) {
                    needsUpdateLabelLine = labelLayoutInnerStore(label).needsUpdateLabelLine;
                }
                if (needsUpdateLabelLine) {
                    this._updateLabelLine(child, seriesModel);
                }

                if (animationEnabled) {
                    this._animateLabels(child, seriesModel);
                }
            });
        });
    }

    private _updateLabelLine(el: Element, seriesModel: SeriesModel) {
        // Only support label being hosted on graphic elements.
        const textEl = el.getTextContent();
        // Update label line style.
        const ecData = getECData(el);
        const dataIndex = ecData.dataIndex;

        // Only support labelLine on the labels represent data.
        if (textEl && dataIndex != null) {
            const data = seriesModel.getData(ecData.dataType);
            const itemModel = data.getItemModel<LabelLineOptionMixin>(dataIndex);

            const defaultStyle: PathStyleProps = {};
            const visualStyle = data.getItemVisual(dataIndex, 'style');
            const visualType = data.getVisual('drawType');
            // Default to be same with main color
            defaultStyle.stroke = visualStyle[visualType];

            const labelLineModel = itemModel.getModel('labelLine');

            setLabelLineStyle(el, getLabelLineStatesModels(itemModel), defaultStyle);

            updateLabelLinePoints(el, labelLineModel);
        }
    }

    private _animateLabels(el: Element, seriesModel: SeriesModel) {
        const textEl = el.getTextContent();
        const guideLine = el.getTextGuideLine();
        // Animate
        if (textEl
            // `forceLabelAnimation` has the highest priority
            && ((el as ECElement).forceLabelAnimation
                || !textEl.ignore
                && !textEl.invisible
                && !(el as ECElement).disableLabelAnimation
                && !isElementRemoved(el)
            )
        ) {
            const layoutStore = labelLayoutInnerStore(textEl);
            const oldLayout = layoutStore.oldLayout;
            const ecData = getECData(el);
            const dataIndex = ecData.dataIndex;
            const newProps = {
                x: textEl.x,
                y: textEl.y,
                rotation: textEl.rotation
            };
            const data = seriesModel.getData(ecData.dataType);

            if (!oldLayout) {
                textEl.attr(newProps);
                // Disable fade in animation if value animation is enabled.
                if (!labelInner(textEl).valueAnimation) {
                    const oldOpacity = retrieve2(textEl.style.opacity, 1);
                    // Fade in animation
                    textEl.style.opacity = 0;
                    initProps(textEl, {
                        style: { opacity: oldOpacity }
                    }, seriesModel, dataIndex);
                }
            }
            else {
                textEl.attr(oldLayout);

                // Make sure the animation from is in the right status.
                const prevStates = el.prevStates;
                if (prevStates) {
                    if (indexOf(prevStates, 'select') >= 0) {
                        textEl.attr(layoutStore.oldLayoutSelect);
                    }
                    if (indexOf(prevStates, 'emphasis') >= 0) {
                        textEl.attr(layoutStore.oldLayoutEmphasis);
                    }
                }
                updateProps(textEl, newProps, seriesModel, dataIndex);
            }
            layoutStore.oldLayout = newProps;

            if (textEl.states.select) {
                const layoutSelect = layoutStore.oldLayoutSelect = {};
                extendWithKeys(layoutSelect, newProps, LABEL_LAYOUT_PROPS);
                extendWithKeys(layoutSelect, textEl.states.select, LABEL_LAYOUT_PROPS);
            }

            if (textEl.states.emphasis) {
                const layoutEmphasis = layoutStore.oldLayoutEmphasis = {};
                extendWithKeys(layoutEmphasis, newProps, LABEL_LAYOUT_PROPS);
                extendWithKeys(layoutEmphasis, textEl.states.emphasis, LABEL_LAYOUT_PROPS);
            }

            animateLabelValue(textEl, dataIndex, data, seriesModel, seriesModel);
        }

        if (guideLine && !guideLine.ignore && !guideLine.invisible) {
            const layoutStore = labelLineAnimationStore(guideLine);
            const oldLayout = layoutStore.oldLayout;
            const newLayout = { points: guideLine.shape.points };
            if (!oldLayout) {
                guideLine.setShape(newLayout);
                guideLine.style.strokePercent = 0;
                initProps(guideLine, {
                    style: { strokePercent: 1 }
                }, seriesModel);
            }
            else {
                guideLine.attr({ shape: oldLayout });
                updateProps(guideLine, {
                    shape: newLayout
                }, seriesModel);
            }

            layoutStore.oldLayout = newLayout;
        }
    }
}


export default LabelManager;