/*
* 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 * as echarts from '../../core/echarts';
// import { createHashMap, each, HashMap, hasOwn, keys, map } from 'zrender/src/core/util';
// import SeriesModel from '../../model/Series';
// import {
//     isCartesian2DDeclaredSeries, findAxisModels, isCartesian2DInjectedAsDataCoordSys
// } from './cartesianAxisHelper';
// import { getDataDimensionsOnAxis } from '../axisHelper';
// import { AxisBaseModel } from '../AxisBaseModel';
// import type Axis from '../Axis';
// import GlobalModel from '../../model/Global';
// import { Dictionary } from '../../util/types';
// import {
//     AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM, ensureScaleRawExtentInfo, ScaleRawExtentInfo, ScaleRawExtentResult
// } from '../scaleRawExtentInfo';
// import { initExtentForUnion, unionExtentFromNumber } from '../../util/model';

/**
 * @obsolete
 * PENDING:
 *  - This file is not used anywhere currently.
 *  - This is a similar behavior to `dataZoom`, but historically supported separately.
 *    Can it be merged into `dataZoom`?
 *  - The impl need to be fixed, @see #15050 , and,
 *      - Remove side-effect.
 *      - Need to fix the case:
 *          series_a =>
 *              x_m (category): dataExtent: [3,8]
 *              y_i:
 *          series_b =>
 *              x_m (category): dataExtent: [4,6]
 *              y_j:
 *          series_c =>
 *              x_m (category): dataExtent: [5,7]
 *              y_j:
 *          dataZoom control y_i, so series_a is excluded.
 *          So x_m.condExtent = [4,6] U [5,7] = [4,7] , and use it to call ensureScaleRawExtentInfo.
 *              (incorrect?, supposed to be [3,8]?)
 *
 * See test case `test/axis-filter-extent.html`.
 *
 * The responsibility of this processor:
 *  Enable category axis to use the specified `min`/`max` to shrink the extent of the orthogonal axis in
 *  Cartesian2D. That is, if some data item on a category axis is out of the range of `min`/`max`, the
 *  extent of the orthogonal axis will exclude the data items.
 *  A typical case is bar-racing, where bars are sorted dynamically and may only need to
 *  displayed part of the whole bars.
 *
 * IMPL_MEMO:
 *  - For each triple xAxis-yAxis-series, if either xAxis or yAxis is controlled by a dataZoom,
 *    the triple should be ignored in this processor.
 *  - Input:
 *    - Cartesian series data ("series approximate extent" has been prepared).
 *    - Axis original `ScaleRawExtentInfo`
 *      (the content comes from ec option and "series approximate extent").
 *  - Modify(result):
 *    - `ScaleRawExtentInfo#min/max` of the determined "target axis".
 *    - "series approximate extent".
 */
// The priority is just after dataZoom processor.
// echarts.registerProcessor(echarts.PRIORITY.PROCESSOR.FILTER + 10, {

//     getTargetSeries: function (ecModel) {
//         const seriesModelMap = createHashMap<SeriesModel>();
//         ecModel.eachSeries(function (seriesModel: SeriesModel) {
//             isCartesian2DDeclaredSeries(seriesModel) && seriesModelMap.set(seriesModel.uid, seriesModel);
//         });
//         return seriesModelMap;
//     },

//     overallReset: function (ecModel, api) {
//         const seriesRecords = [] as SeriesRecord[];
//         const axisRecordMap = createHashMap<AxisRecord>();

//         prepareDataExtentOnAxis(ecModel, axisRecordMap, seriesRecords);
//         calculateFilteredExtent(axisRecordMap, seriesRecords);
//         shrinkAxisExtent(axisRecordMap);
//     }
// });

// type AxisRecord = {
//     rawExtentInfo?: ScaleRawExtentInfo;
//     rawExtentResult?: ScaleRawExtentResult;
//     tarExtent?: number[];
// };

// type SeriesRecord = {
//     seriesModel: SeriesModel;
//     xAxisModel: AxisBaseModel;
//     yAxisModel: AxisBaseModel;
// };

// function prepareDataExtentOnAxis(
//     ecModel: GlobalModel,
//     axisRecordMap: HashMap<AxisRecord>,
//     seriesRecords: SeriesRecord[]
// ): void {
//     ecModel.eachSeries(function (seriesModel: SeriesModel) {
//         // If pie (or other similar series) use cartesian2d, the logic below is
//         // probably wrong, therefore skip it temporarily.
//         // TODO: support union extent in this case.
//         //  e.g. make a fake seriesData by series.coord/series.center, and it can be
//         //  performed by data processing (such as, filter), and applied here.
//         if (!isCartesian2DInjectedAsDataCoordSys(seriesModel)) {
//             return;
//         }

//         const axesModelMap = findAxisModels(seriesModel);
//         const xAxisModel = axesModelMap.xAxisModel;
//         const yAxisModel = axesModelMap.yAxisModel;
//         const xAxis = xAxisModel.axis;
//         const yAxis = yAxisModel.axis;
//         const xRawExtentInfo = ensureScaleRawExtentInfo(xAxis);
//         const yRawExtentInfo = ensureScaleRawExtentInfo(yAxis);

//         // If either axis controlled by other filter like "dataZoom",
//         // use the rule of dataZoom rather than adopting the rules here.
//         if (
//             (xRawExtentInfo && xRawExtentInfo.from === AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM)
//             || (yRawExtentInfo && yRawExtentInfo.from === AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM)
//         ) {
//             return;
//         }

//         seriesRecords.push({
//             seriesModel: seriesModel,
//             xAxisModel: xAxisModel,
//             yAxisModel: yAxisModel
//         });
//     });
// }

// function calculateFilteredExtent(
//     axisRecordMap: HashMap<AxisRecord>,
//     seriesRecords: SeriesRecord[]
// ) {
//     each(seriesRecords, function (seriesRecord) {
//         const xAxisModel = seriesRecord.xAxisModel;
//         const yAxisModel = seriesRecord.yAxisModel;
//         const xAxis = xAxisModel.axis;
//         const yAxis = yAxisModel.axis;
//         const xAxisRecord = prepareAxisRecord(axisRecordMap, xAxisModel);
//         const yAxisRecord = prepareAxisRecord(axisRecordMap, yAxisModel);
//         xAxisRecord.rawExtentInfo = ensureScaleRawExtentInfo(xAxis);
//         yAxisRecord.rawExtentInfo = ensureScaleRawExtentInfo(yAxis);
//         xAxisRecord.rawExtentResult = xAxisRecord.rawExtentInfo.calculate();
//         yAxisRecord.rawExtentResult = yAxisRecord.rawExtentInfo.calculate();

//         const data = seriesRecord.seriesModel.getData();
//         // For duplication removal.
//         // key: series data dimension corresponding to the condition axis.
//         const condDimMap: Dictionary<boolean> = {};
//         // key: series data dimension corresponding to the target axis.
//         const tarDimMap: Dictionary<boolean> = {};
//         let condAxis: Axis;
//         let tarAxisRecord: AxisRecord;

//         function addCondition(axis: Axis, axisRecord: AxisRecord) {
//             // But for simplicity and safety and performance, we only adopt this
//             // feature on category axis at present.
//             const rawExtentResult = axisRecord.rawExtentResult;
//             if (axis.type === 'category'
//                 && (rawExtentResult.dataMinMax[0] < rawExtentResult.resultMinMax[0]
//                     || rawExtentResult.resultMinMax[1] < rawExtentResult.dataMinMax[1]
//                 )
//             ) {
//                 each(getDataDimensionsOnAxis(data, axis.dim), function (dataDim) {
//                     if (!hasOwn(condDimMap, dataDim)) {
//                         condDimMap[dataDim] = true;
//                         condAxis = axis;
//                     }
//                 });
//             }
//         }
//         function addTarget(axis: Axis, axisRecord: AxisRecord) {
//             const rawExtentResult = axisRecord.rawExtentResult;
//             const fixMinMax = rawExtentResult.fixMinMax;
//             if (axis.type !== 'category'
//                 && (!fixMinMax[0] || !fixMinMax[1])
//             ) {
//                 each(getDataDimensionsOnAxis(data, axis.dim), function (dataDim) {
//                     if (!hasOwn(condDimMap, dataDim) && !hasOwn(tarDimMap, dataDim)) {
//                         tarDimMap[dataDim] = true;
//                         tarAxisRecord = axisRecord;
//                     }
//                 });
//             }
//         }

//         addCondition(xAxis, xAxisRecord);
//         addCondition(yAxis, yAxisRecord);
//         addTarget(xAxis, xAxisRecord);
//         addTarget(yAxis, yAxisRecord);

//         const condDims = keys(condDimMap);
//         const tarDims = keys(tarDimMap);
//         const tarDimExtents = map(tarDims, function () {
//             return initExtentForUnion();
//         });

//         const condDimsLen = condDims.length;
//         const tarDimsLen = tarDims.length;

//         if (!condDimsLen || !tarDimsLen) {
//             return;
//         }

//         const singleCondDim = condDimsLen === 1 ? condDims[0] : null;
//         const singleTarDim = tarDimsLen === 1 ? tarDims[0] : null;
//         const dataLen = data.count();

//         // Time consuming, because this is a "block task".
//         // Simple optimization for the vast majority of cases.
//         if (singleCondDim && singleTarDim) {
//             for (let dataIdx = 0; dataIdx < dataLen; dataIdx++) {
//                 const condVal = data.get(singleCondDim, dataIdx) as number;
//                 if (condAxis.scale.contain(condVal)) {
//                     unionExtentFromNumber(tarDimExtents[0], data.get(singleTarDim, dataIdx) as number);
//                 }
//             }
//         }
//         else {
//             for (let dataIdx = 0; dataIdx < dataLen; dataIdx++) {
//                 for (let j = 0; j < condDimsLen; j++) {
//                     const condVal = data.get(condDims[j], dataIdx) as number;
//                     if (condAxis.scale.contain(condVal)) {
//                         for (let k = 0; k < tarDimsLen; k++) {
//                             unionExtentFromNumber(tarDimExtents[k], data.get(tarDims[k], dataIdx) as number);
//                         }
//                         // Any one dim is in range means satisfied.
//                         break;
//                     }
//                 }
//             }
//         }

//         each(tarDimExtents, function (tarDimExtent, i) {
//             // FIXME: if there has been approximateExtent set?
//             data.setApproximateExtent(tarDimExtent as [number, number], tarDims[i]);
//             const tarAxisExtent = tarAxisRecord.tarExtent = tarAxisRecord.tarExtent || initExtentForUnion();
//             unionExtentFromNumber(tarAxisExtent, tarDimExtent[0]);
//             unionExtentFromNumber(tarAxisExtent, tarDimExtent[1]);
//         });
//     });
// }

// function shrinkAxisExtent(axisRecordMap: HashMap<AxisRecord>) {
//     axisRecordMap.each(function (axisRecord) {
//         const tarAxisExtent = axisRecord.tarExtent;
//         if (tarAxisExtent) {
//             const rawExtentResult = axisRecord.rawExtentResult;
//             const fixMinMax = rawExtentResult.fixMinMax;
//             // const rawExtentInfo = axisRecord.rawExtentInfo;
//             // Shrink the original extent.
//             if (!fixMinMax[0] && tarAxisExtent[0] > rawExtentResult.resultMinMax[0]) {
//                 // rawExtentInfo.modifyDataMinMax('min', tarAxisExtent[0]);
//             }
//             if (!fixMinMax[1] && tarAxisExtent[1] < rawExtentResult.resultMinMax[1]) {
//                 // rawExtentInfo.modifyDataMinMax('max', tarAxisExtent[1]);
//             }
//         }
//     });
// }

// function prepareAxisRecord(
//     axisRecordMap: HashMap<AxisRecord>,
//     axisModel: AxisBaseModel
// ): AxisRecord {
//     return axisRecordMap.get(axisModel.uid)
//         || axisRecordMap.set(axisModel.uid, {});
// }
