/*
* 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 { StageHandler, SeriesOption, SeriesSamplingOptionMixin } from '../util/types';
import { Dictionary } from 'zrender/src/core/types';
import SeriesModel from '../model/Series';
import { isFunction, isString } from 'zrender/src/core/util';


type Sampler = (frame: ArrayLike<number>) => number;
const samplers: Dictionary<Sampler> = {
    average: function (frame) {
        let sum = 0;
        let count = 0;
        for (let i = 0; i < frame.length; i++) {
            if (!isNaN(frame[i])) {
                sum += frame[i];
                count++;
            }
        }
        // Return NaN if count is 0
        return count === 0 ? NaN : sum / count;
    },
    sum: function (frame) {
        let sum = 0;
        for (let i = 0; i < frame.length; i++) {
            // Ignore NaN
            sum += frame[i] || 0;
        }
        return sum;
    },
    max: function (frame) {
        let max = -Infinity;
        for (let i = 0; i < frame.length; i++) {
            frame[i] > max && (max = frame[i]);
        }
        // NaN will cause illegal axis extent.
        return isFinite(max) ? max : NaN;
    },
    min: function (frame) {
        let min = Infinity;
        for (let i = 0; i < frame.length; i++) {
            frame[i] < min && (min = frame[i]);
        }
        // NaN will cause illegal axis extent.
        return isFinite(min) ? min : NaN;
    },
    minmax: function (frame) {
        let turningPointAbsoluteValue = -Infinity;
        let turningPointOriginalValue = -Infinity;

        for (let i = 0; i < frame.length; i++) {
            const originalValue = frame[i];
            const absoluteValue = Math.abs(originalValue);

            if (absoluteValue > turningPointAbsoluteValue) {
                turningPointAbsoluteValue = absoluteValue;
                turningPointOriginalValue = originalValue;
            }
        }

        return isFinite(turningPointOriginalValue) ? turningPointOriginalValue : NaN;
    },
    // TODO
    // Median
    nearest: function (frame) {
        return frame[0];
    }
};

const indexSampler = function (frame: ArrayLike<number>) {
    return Math.round(frame.length / 2);
};

export default function dataSample(seriesType: string): StageHandler {
    return {

        seriesType: seriesType,

        // FIXME:TS never used, so comment it
        // modifyOutputEnd: true,

        reset: function (seriesModel: SeriesModel<SeriesOption & SeriesSamplingOptionMixin>, ecModel, api) {
            const data = seriesModel.getData();
            const sampling = seriesModel.get('sampling');
            const coordSys = seriesModel.coordinateSystem;
            const count = data.count();
            // Only cartesian2d support down sampling. Disable it when there is few data.
            if (count > 10 && coordSys.type === 'cartesian2d' && sampling) {
                const baseAxis = coordSys.getBaseAxis();
                const valueAxis = coordSys.getOtherAxis(baseAxis);
                const extent = baseAxis.getExtent();
                const dpr = api.getDevicePixelRatio();
                // Coordinste system has been resized
                const size = Math.abs(extent[1] - extent[0]) * (dpr || 1);
                const rate = Math.round(count / size);

                if (isFinite(rate) && rate > 1) {
                    if (sampling === 'lttb') {
                        seriesModel.setData(data.lttbDownSample(data.mapDimension(valueAxis.dim), 1 / rate));
                    }
                    let sampler;
                    if (isString(sampling)) {
                        sampler = samplers[sampling];
                    }
                    else if (isFunction(sampling)) {
                        sampler = sampling;
                    }
                    if (sampler) {
                        // Only support sample the first dim mapped from value axis.
                        seriesModel.setData(data.downSample(
                            data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler
                        ));
                    }
                }
            }
        }
    };
}
