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

package org.apache.poi.ss.util;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * Represents a transformation of a 64 bit IEEE double quantity having a decimal exponent and a
 * fixed point (15 decimal digit) significand.  Some quirks of Excel's calculation behaviour are
 * simpler to reproduce with numeric quantities in this format.  This class is currently used to
 * help:
 * <ol>
 * <li>Comparison operations</li>
 * <li>Conversions to text</li>
 * </ol>
 *
 * <p>
 * This class does not handle negative numbers or zero.
 * <p>
 * The value of a {@link NormalisedDecimal} is given by<br>
 * <tt> significand &times; 10<sup>decimalExponent</sup></tt>
 * <br>
 * where:<br>
 *
 * {@code significand} = wholePart + fractionalPart / 2<sup>24</sup><br>
 */
final class NormalisedDecimal {
	/**
	 * Number of powers of ten contained in the significand
	 */
	private static final int EXPONENT_OFFSET = 14;

	private static final BigDecimal BD_2_POW_24 = new BigDecimal(BigInteger.ONE.shiftLeft(24));

	/**
	 * log<sub>10</sub>(2)&times;2<sup>20</sup>
	 */
	private static final int LOG_BASE_10_OF_2_TIMES_2_POW_20 = 315653; // 315652.8287

	/**
	 * 2<sup>19</sup>
	 */
	private static final int C_2_POW_19 = 1 << 19;


	/**
	 * the value of {@link #_fractionalPart} that represents 0.5
	 */
	private static final int FRAC_HALF = 0x800000;

	/**
	 * 10<sup>15</sup>
	 */
	private static final long MAX_REP_WHOLE_PART = 0x38D7EA4C68000L;


	@SuppressWarnings("java:S128")
	public static NormalisedDecimal create(BigInteger frac, int binaryExponent) {
		// estimate pow2&pow10 first, perform optional mulShift, then normalize
		int pow10;
		if (binaryExponent > 49 || binaryExponent < 46) {

			// working with ints (left shifted 20) instead of doubles
			// x = 14.5 - binaryExponent * log10(2);
			int x = (29 << 19) - binaryExponent * LOG_BASE_10_OF_2_TIMES_2_POW_20;
			x += C_2_POW_19; // round
			pow10 = -(x >> 20);
		} else {
			pow10 = 0;
		}
		MutableFPNumber cc = new MutableFPNumber(frac, binaryExponent);
		if (pow10 != 0) {
			cc.multiplyByPowerOfTen(-pow10);
		}

		switch (cc.get64BitNormalisedExponent()) {
			case 46:
				if (cc.isAboveMinRep()) {
					break;
				}
			case 44:
			case 45:
				cc.multiplyByPowerOfTen(1);
				pow10--;
				break;
			case 47:
			case 48:
				break;
			case 49:
				if (cc.isBelowMaxRep()) {
					break;
				}
			case 50:
				cc.multiplyByPowerOfTen(-1);
				pow10++;
				break;

			default:
				throw new IllegalStateException("Bad binary exp " + cc.get64BitNormalisedExponent() + ".");
		}
		cc.normalise64bit();

		return cc.createNormalisedDecimal(pow10);
	}

	/**
	 * Rounds at the digit with value 10<sup>decimalExponent</sup>
	 */
	public NormalisedDecimal roundUnits() {
		long wholePart = _wholePart;
		if (_fractionalPart >= FRAC_HALF) {
			wholePart++;
		}

		int de = _relativeDecimalExponent;

		if (wholePart < MAX_REP_WHOLE_PART) {
			return new NormalisedDecimal(wholePart, 0, de);
		}
		return new NormalisedDecimal(wholePart/10, 0, de+1);
	}

	/**
	 * The decimal exponent increased by one less than the digit count of {@link #_wholePart}
	 */
	private final int _relativeDecimalExponent;
	/**
	 * The whole part of the significand (typically 15 digits).
	 *
	 * 47-50 bits long (MSB may be anywhere from bit 46 to 49)
	 * LSB is units bit.
	 */
	private final long _wholePart;
	/**
	 * The fractional part of the significand.
	 * 24 bits (only top 14-17 bits significant): a value between 0x000000 and 0xFFFF80
	 */
	private final int _fractionalPart;


	NormalisedDecimal(long wholePart, int fracPart, int decimalExponent) {
		_wholePart = wholePart;
		_fractionalPart = fracPart;
		_relativeDecimalExponent = decimalExponent;
	}


	/**
	 * Convert to an equivalent {@link ExpandedDouble} representation (binary frac and exponent).
	 * The resulting transformed object is easily converted to a 64 bit IEEE double:
	 * <ul>
	 * <li>bits 2-53 of the {@link #composeFrac()} become the 52 bit 'fraction'.</li>
	 * <li>{@link #getDecimalExponent()} is biased by 1023 to give the 'exponent'.</li>
	 * </ul>
	 * The sign bit must be obtained from somewhere else.
	 * @return a new NormalisedDecimal normalised to base 2 representation.
	 */
	public ExpandedDouble normaliseBaseTwo() {
		MutableFPNumber cc = new MutableFPNumber(composeFrac(), 39);
		cc.multiplyByPowerOfTen(_relativeDecimalExponent);
		cc.normalise64bit();
		return cc.createExpandedDouble();
	}

	/**
	 * @return the significand as a fixed point number (with 24 fraction bits and 47-50 whole bits)
	 */
	BigInteger composeFrac() {
		return BigInteger.valueOf(_wholePart).shiftLeft(24).or(BigInteger.valueOf(_fractionalPart & 0x00FFFFFF));
	}

	public String getSignificantDecimalDigits() {
		return Long.toString(_wholePart);
	}
	/**
	 * Rounds the first whole digit position (considers only units digit, not frational part).
	 * Caller should check total digit count of result to see whether the rounding operation caused
	 * a carry out of the most significant digit
	 */
	public String getSignificantDecimalDigitsLastDigitRounded() {
		long wp = _wholePart + 5; // rounds last digit
		StringBuilder sb = new StringBuilder(24);
		sb.append(wp);
		sb.setCharAt(sb.length()-1, '0');
		return sb.toString();
	}

	/**
	 * @return the number of powers of 10 which have been extracted from the significand and binary exponent.
	 */
	public int getDecimalExponent() {
		return _relativeDecimalExponent+EXPONENT_OFFSET;
	}

	/**
	 * assumes both this and other are normalised
	 */
	public int compareNormalised(NormalisedDecimal other) {
		int cmp = _relativeDecimalExponent - other._relativeDecimalExponent;
		if (cmp != 0) {
			return cmp;
		}
		if (_wholePart > other._wholePart) {
			return 1;
		}
		if (_wholePart < other._wholePart) {
			return -1;
		}
		return _fractionalPart - other._fractionalPart;
	}
	public BigDecimal getFractionalPart() {
		return new BigDecimal(_fractionalPart).divide(BD_2_POW_24);
	}

	private String getFractionalDigits() {
		if (_fractionalPart == 0) {
			return "0";
		}
		return getFractionalPart().toString().substring(2);
	}

	@Override
	public String toString() {

		StringBuilder sb = new StringBuilder();
		sb.append(getClass().getName());
		sb.append(" [");
		String ws = String.valueOf(_wholePart);
		sb.append(ws.charAt(0));
		sb.append('.');
		sb.append(ws.substring(1));
		sb.append(' ');
		sb.append(getFractionalDigits());
		sb.append("E");
		sb.append(getDecimalExponent());
		sb.append("]");
		return sb.toString();
	}
}
