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


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* 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 { subPixelOptimize } from '../../util/graphic.js';
import createRenderPlanner from '../helper/createRenderPlanner.js';
import { map } from 'tvrender/lib/core/util.js';
import { isMobileRender } from "../../util/mobile.js";
var positiveBorderColorQuery = ['itemStyle', 'borderColor'];
var negativeBorderColorQuery = ['itemStyle', 'borderColor0'];
var dojiBorderColorQuery = ['itemStyle', 'borderColorDoji'];
var positiveColorQuery = ['itemStyle', 'color'];
var negativeColorQuery = ['itemStyle', 'color0'];
var positiveWickColorQuery = ['itemStyle', 'wickColor'];
var negativeWickColorQuery = ['itemStyle', 'wickColor0'];
function getColor(sign, model, ignoreParentColor) {
  return model.get(sign > 0 ? positiveColorQuery : negativeColorQuery, ignoreParentColor);
}
function getBorderColor(sign, model, ignoreParentColor) {
  return model.get(sign === 0 ? dojiBorderColorQuery : sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery, ignoreParentColor);
}
function getWickColor(sign, model, ignoreParentColor) {
  return model.get(sign > 0 ? positiveWickColorQuery : negativeWickColorQuery, ignoreParentColor);
}
var heikinAshiLayout = {
  seriesType: 'heikinAshi',
  plan: createRenderPlanner(),
  reset: function (seriesModel) {
    var coordSys = seriesModel.coordinateSystem;
    var data = seriesModel.getData();
    var candleWidth = calculateCandleWidth(seriesModel, data);
    var cDimIdx = 0;
    var vDimIdx = 1;
    var coordDims = ['x', 'y'];
    var cDimI = data.getDimensionIndex(data.mapDimension(coordDims[cDimIdx]));
    var vDimsI = map(data.mapDimensionsAll(coordDims[vDimIdx]), data.getDimensionIndex, data);
    var openDimI = vDimsI[0];
    var closeDimI = vDimsI[1];
    var lowestDimI = vDimsI[2];
    var highestDimI = vDimsI[3];
    var isSimpleBox = candleWidth <= 1.3;
    if (cDimI < 0 || vDimsI.length < 4) {
      return;
    }
    var showLast = seriesModel.get('showLast');
    var ignoreParentColor = seriesModel.get('ignoreParentColor');
    var signByPrev = seriesModel.get('signByPrev');
    var offsetX = isMobileRender ? 0 : 0.5;
    var formatY = isMobileRender ? function (y) {
      return y;
    } : function (y) {
      return Math.floor(y);
    };
    return {
      progress: normalProgress
    };
    function normalProgress(params, candleData) {
      var store = candleData.getStore();
      var bodyPointsByColor = {};
      var wickPointsByColor = {};
      var lastIndex = candleData.count(true) - 1;
      for (var dataIndex = params.start; dataIndex < params.end; dataIndex++) {
        if (showLast && lastIndex - candleData.getRawIndex(dataIndex) >= showLast) {
          continue;
        }
        var axisDimVal = store.get(cDimI, dataIndex);
        var openVal = store.get(openDimI, dataIndex);
        var closeVal = store.get(closeDimI, dataIndex);
        var lowestVal = store.get(lowestDimI, dataIndex);
        var highestVal = store.get(highestDimI, dataIndex);
        var ocLow = Math.min(openVal, closeVal);
        var ocHigh = Math.max(openVal, closeVal);
        var _a = coordSys.dataToPoint([axisDimVal, ocLow]),
          ocLowX = _a[0],
          ocLowY = _a[1];
        var x = ocLowX + offsetX;
        var ocLowPoint = [x, formatY(ocLowY)];
        var ocHighPoint = coordSys.dataToPoint([axisDimVal, ocHigh]);
        ocHighPoint[0] = x;
        ocHighPoint[1] = formatY(ocHighPoint[1]);
        var lowestPoint = coordSys.dataToPoint([axisDimVal, lowestVal]);
        lowestPoint[0] = x;
        lowestPoint[1] = formatY(lowestPoint[1]);
        var highestPoint = coordSys.dataToPoint([axisDimVal, highestVal]);
        highestPoint[0] = x;
        highestPoint[1] = formatY(highestPoint[1]);
        var itemModel = candleData.getItemModel(dataIndex);
        // const hasDojiColor = !!itemModel.get(['itemStyle', 'borderColorDoji']);
        var sign = getSign(store, dataIndex, openVal, closeVal, closeDimI, signByPrev);
        var color = getColor(sign, itemModel, ignoreParentColor);
        var border = getBorderColor(sign, itemModel, ignoreParentColor);
        if (!color && !border) {
          continue;
        }
        var key = (color || 'none') + ":" + (border || 'none');
        var bodyPoints = bodyPointsByColor[key] || [];
        if (isSimpleBox) {
          bodyPoints.push(ocHighPoint, lowestPoint);
        } else {
          addBodyEnd(bodyPoints, ocHighPoint, 0);
          addBodyEnd(bodyPoints, ocLowPoint, 1);
        }
        bodyPointsByColor[key] = bodyPoints;
        var wickKey = getWickColor(sign, itemModel, ignoreParentColor);
        if (wickKey) {
          var wickPoint = wickPointsByColor[wickKey] || [];
          wickPoint.push(highestPoint, ocHighPoint, lowestPoint, ocLowPoint);
          wickPointsByColor[wickKey] = wickPoint;
        }
      }
      candleData.setLayout({
        bodyPointsByColor: bodyPointsByColor,
        wickPointsByColor: wickPointsByColor,
        isSimpleBox: isSimpleBox
      });
      function addBodyEnd(ends, point, start) {
        var point1 = point.slice();
        var point2 = point.slice();
        // point1[cDimIdx] = subPixelOptimize(
        //     point1[cDimIdx] + candleWidth / 2, 1, false
        // );
        // point2[cDimIdx] = subPixelOptimize(
        //     point2[cDimIdx] - candleWidth / 2, 1, true
        // );
        point1[0] = point1[0] - Math.floor(candleWidth * 0.5);
        point2[0] = point1[0] + candleWidth;
        point1[1] += 0.5;
        point2[1] += 0.5;
        start ? ends.push(point1, point2) : ends.push(point2, point1);
      }
      function subPixelOptimizePoint(point) {
        point[cDimIdx] = subPixelOptimize(point[cDimIdx], 1);
        return point;
      }
    }
  }
};
/**
 * Get the sign of a single data.
 *
 * @returns 0 for doji with hasDojiColor: true,
 *          1 for positive,
 *          -1 for negative.
 */
function getSign(store, dataIndex, openVal, closeVal, closeDimI, signByPrev) {
  var sign;
  if (signByPrev) {
    var index = store.getRawIndex(dataIndex);
    if (index > 0) return store.getByRawIndex(closeDimI, index - 1) <= closeVal ? 1 : -1;
  }
  if (openVal > closeVal) {
    sign = -1;
  } else if (openVal <= closeVal) {
    sign = 1;
  }
  return sign;
}
// export function optimalCandlestickWidth(barSpacing: number, pixelRatio: number): number {
// 	const barSpacingSpecialCaseFrom = 2.5;
// 	const barSpacingSpecialCaseTo = 4;
// 	const barSpacingSpecialCaseCoeff = 3;
// 	if (barSpacing >= barSpacingSpecialCaseFrom && barSpacing <= barSpacingSpecialCaseTo) {
// 		return Math.floor(barSpacingSpecialCaseCoeff * pixelRatio);
// 	}
//     else if (barSpacing > barSpacingSpecialCaseTo && barSpacing <= 7.5) {
//         return Math.floor(Math.max(barSpacing * 0.72, 1));
//     }
// 	// coeff should be 1 on small barspacing and go to 0.8 while groing bar spacing
// 	const barSpacingReducingCoeff = 0.2;
// 	const coeff = 1 - barSpacingReducingCoeff * Math.atan(Math.max(barSpacingSpecialCaseTo, barSpacing) - barSpacingSpecialCaseTo) / (Math.PI * 0.5);
// 	const res = Math.floor(barSpacing * coeff * pixelRatio);
// 	const scaledBarSpacing = Math.floor(barSpacing * pixelRatio);
// 	const optimal = Math.min(res, scaledBarSpacing);
// 	return Math.max(Math.floor(pixelRatio), optimal);
// }
function calculateCandleWidth(seriesModel, data) {
  var baseAxis = seriesModel.getBaseAxis();
  var extent;
  var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : (extent = baseAxis.getExtent(), Math.abs(extent[1] - extent[0]) / data.count());
  var width = optimalCandlestickWidth(bandWidth, 1);
  return width >= 2 && width % 2 === 1 ? width - 1 : width;
  // return Math.floor(Math.max(bandWidth * 0.7, 1));
}

function optimalCandlestickWidth(barSpacing, pixelRatio) {
  if (barSpacing >= 2.5 && barSpacing <= 4) return Math.floor(3 * pixelRatio) - 1;
  var n = 1 - .2 * Math.atan(Math.max(4, barSpacing) - 4) / (.5 * Math.PI),
    i = Math.floor(barSpacing * n * pixelRatio),
    s = Math.floor(barSpacing * pixelRatio),
    r = Math.min(i, s - 1, Math.round(barSpacing - 2));
  return Math.max(Math.floor(pixelRatio), r);
}
export function getRenderIndexX(bandWidth, x) {
  return subPixelOptimize(x - bandWidth / 2, 1, false);
}
export default heikinAshiLayout;