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


/**
 * Excel converts numbers to text with different rules to those of java, so
 *  <code>Double.toString(value)</tt> won't do.
 * <ul>
 * <li>No more than 15 significant figures are output (java does 18).</li>
 * <li>The sign char for the exponent is included even if positive</li>
 * <li>Special values (<tt>NaN</tt> and <tt>Infinity</tt>) get rendered like the ordinary
 * number that the bit pattern represents.</li>
 * <li>Denormalised values (between &plusmn;2<sup>-1074</sup> and &plusmn;2<sup>-1022</sup>
 *  are displayed as "0"</sup>
 * </ul>
 * IEEE 64-bit Double Rendering Comparison
 *
 * <table border="1" cellpadding="2" cellspacing="0" summary="IEEE 64-bit Double Rendering Comparison">
 * <tr><th>Raw bits</th><th>Java</th><th>Excel</th></tr>
 *
 * <tr><td>0x0000000000000000L</td><td>0.0</td><td>0</td></tr>
 * <tr><td>0x3FF0000000000000L</td><td>1.0</td><td>1</td></tr>
 * <tr><td>0x3FF00068DB8BAC71L</td><td>1.0001</td><td>1.0001</td></tr>
 * <tr><td>0x4087A00000000000L</td><td>756.0</td><td>756</td></tr>
 * <tr><td>0x401E3D70A3D70A3DL</td><td>7.56</td><td>7.56</td></tr>
 * <tr><td>0x405EDD3C07FB4C99L</td><td>123.45678901234568</td><td>123.456789012346</td></tr>
 * <tr><td>0x4132D687E3DF2180L</td><td>1234567.8901234567</td><td>1234567.89012346</td></tr>
 * <tr><td>0x3EE9E409302678BAL</td><td>1.2345678901234568E-5</td><td>1.23456789012346E-05</td></tr>
 * <tr><td>0x3F202E85BE180B74L</td><td>1.2345678901234567E-4</td><td>0.000123456789012346</td></tr>
 * <tr><td>0x3F543A272D9E0E51L</td><td>0.0012345678901234567</td><td>0.00123456789012346</td></tr>
 * <tr><td>0x3F8948B0F90591E6L</td><td>0.012345678901234568</td><td>0.0123456789012346</td></tr>
 * <tr><td>0x3EE9E409301B5A02L</td><td>1.23456789E-5</td><td>0.0000123456789</td></tr>
 * <tr><td>0x3E6E7D05BDABDE50L</td><td>5.6789012345E-8</td><td>0.000000056789012345</td></tr>
 * <tr><td>0x3E6E7D05BDAD407EL</td><td>5.67890123456E-8</td><td>5.67890123456E-08</td></tr>
 * <tr><td>0x3E6E7D06029F18BEL</td><td>5.678902E-8</td><td>0.00000005678902</td></tr>
 * <tr><td>0x2BCB5733CB32AE6EL</td><td>9.999999999999123E-98</td><td>9.99999999999912E-98</td></tr>
 * <tr><td>0x2B617F7D4ED8C59EL</td><td>1.0000000000001235E-99</td><td>1.0000000000001E-99</td></tr>
 * <tr><td>0x0036319916D67853L</td><td>1.2345678901234578E-307</td><td>1.2345678901235E-307</td></tr>
 * <tr><td>0x359DEE7A4AD4B81FL</td><td>2.0E-50</td><td>2E-50</td></tr>
 * <tr><td>0x41678C29DCD6E9E0L</td><td>1.2345678901234567E7</td><td>12345678.9012346</td></tr>
 * <tr><td>0x42A674E79C5FE523L</td><td>1.2345678901234568E13</td><td>12345678901234.6</td></tr>
 * <tr><td>0x42DC12218377DE6BL</td><td>1.2345678901234567E14</td><td>123456789012346</td></tr>
 * <tr><td>0x43118B54F22AEB03L</td><td>1.2345678901234568E15</td><td>1234567890123460</td></tr>
 * <tr><td>0x43E56A95319D63E1L</td><td>1.2345678901234567E19</td><td>12345678901234600000</td></tr>
 * <tr><td>0x441AC53A7E04BCDAL</td><td>1.2345678901234568E20</td><td>1.23456789012346E+20</td></tr>
 * <tr><td>0xC3E56A95319D63E1L</td><td>-1.2345678901234567E19</td><td>-12345678901234600000</td></tr>
 * <tr><td>0xC41AC53A7E04BCDAL</td><td>-1.2345678901234568E20</td><td>-1.23456789012346E+20</td></tr>
 * <tr><td>0x54820FE0BA17F46DL</td><td>1.2345678901234577E99</td><td>1.2345678901235E+99</td></tr>
 * <tr><td>0x54B693D8E89DF188L</td><td>1.2345678901234576E100</td><td>1.2345678901235E+100</td></tr>
 * <tr><td>0x4A611B0EC57E649AL</td><td>2.0E50</td><td>2E+50</td></tr>
 * <tr><td>0x7FEFFFFFFFFFFFFFL</td><td>1.7976931348623157E308</td><td>1.7976931348623E+308</td></tr>
 * <tr><td>0x0010000000000000L</td><td>2.2250738585072014E-308</td><td>2.2250738585072E-308</td></tr>
 * <tr><td>0x000FFFFFFFFFFFFFL</td><td>2.225073858507201E-308</td><td>0</td></tr>
 * <tr><td>0x0000000000000001L</td><td>4.9E-324</td><td>0</td></tr>
 * <tr><td>0x7FF0000000000000L</td><td>Infinity</td><td>1.7976931348623E+308</td></tr>
 * <tr><td>0xFFF0000000000000L</td><td>-Infinity</td><td>1.7976931348623E+308</td></tr>
 * <tr><td>0x441AC7A08EAD02F2L</td><td>1.234999999999999E20</td><td>1.235E+20</td></tr>
 * <tr><td>0x40FE26BFFFFFFFF9L</td><td>123499.9999999999</td><td>123500</td></tr>
 * <tr><td>0x3E4A857BFB2F2809L</td><td>1.234999999999999E-8</td><td>0.00000001235</td></tr>
 * <tr><td>0x3BCD291DEF868C89L</td><td>1.234999999999999E-20</td><td>1.235E-20</td></tr>
 * <tr><td>0x444B1AE4D6E2EF4FL</td><td>9.999999999999999E20</td><td>1E+21</td></tr>
 * <tr><td>0x412E847FFFFFFFFFL</td><td>999999.9999999999</td><td>1000000</td></tr>
 * <tr><td>0x3E45798EE2308C39L</td><td>9.999999999999999E-9</td><td>0.00000001</td></tr>
 * <tr><td>0x3C32725DD1D243ABL</td><td>9.999999999999999E-19</td><td>0.000000000000000001</td></tr>
 * <tr><td>0x3BFD83C94FB6D2ABL</td><td>9.999999999999999E-20</td><td>1E-19</td></tr>
 * <tr><td>0xC44B1AE4D6E2EF4FL</td><td>-9.999999999999999E20</td><td>-1E+21</td></tr>
 * <tr><td>0xC12E847FFFFFFFFFL</td><td>-999999.9999999999</td><td>-1000000</td></tr>
 * <tr><td>0xBE45798EE2308C39L</td><td>-9.999999999999999E-9</td><td>-0.00000001</td></tr>
 * <tr><td>0xBC32725DD1D243ABL</td><td>-9.999999999999999E-19</td><td>-0.000000000000000001</td></tr>
 * <tr><td>0xBBFD83C94FB6D2ABL</td><td>-9.999999999999999E-20</td><td>-1E-19</td></tr>
 * <tr><td>0xFFFF0420003C0000L</td><td>NaN</td><td>3.484840871308E+308</td></tr>
 * <tr><td>0x7FF8000000000000L</td><td>NaN</td><td>2.6965397022935E+308</td></tr>
 * <tr><td>0x7FFF0420003C0000L</td><td>NaN</td><td>3.484840871308E+308</td></tr>
 * <tr><td>0xFFF8000000000000L</td><td>NaN</td><td>2.6965397022935E+308</td></tr>
 * <tr><td>0xFFFF0AAAAAAAAAAAL</td><td>NaN</td><td>3.4877119413344E+308</td></tr>
 * <tr><td>0x7FF80AAAAAAAAAAAL</td><td>NaN</td><td>2.7012211948322E+308</td></tr>
 * <tr><td>0xFFFFFFFFFFFFFFFFL</td><td>NaN</td><td>3.5953862697246E+308</td></tr>
 * <tr><td>0x7FFFFFFFFFFFFFFFL</td><td>NaN</td><td>3.5953862697246E+308</td></tr>
 * <tr><td>0xFFF7FFFFFFFFFFFFL</td><td>NaN</td><td>2.6965397022935E+308</td></tr>
 * </table>
 *
 * <b>Note</b>:
 * Excel has inconsistent rules for the following numeric operations:
 * <ul>
 * <li>Conversion to string (as handled here)</li>
 * <li>Rendering numerical quantities in the cell grid.</li>
 * <li>Conversion from text</li>
 * <li>General arithmetic</li>
 * </ul>
 * Excel's text to number conversion is not a true <i>inverse</i> of this operation.  The
 * allowable ranges are different.  Some numbers that don't correctly convert to text actually
 * <b>do</b> get handled properly when used in arithmetic evaluations.
 *
 * @author Josh Micich
 */
public final class NumberToTextConverter {

	private static final long EXCEL_NAN_BITS = 0xFFFF0420003C0000L;
	private static final int MAX_TEXT_LEN = 20;

	private NumberToTextConverter() {
		// no instances of this class
	}

	/**
	 * Converts the supplied <tt>value</tt> to the text representation that Excel would give if
	 * the value were to appear in an unformatted cell, or as a literal number in a formula.<br>
	 * Note - the results from this method differ slightly from those of <tt>Double.toString()</tt>
	 * In some special cases Excel behaves quite differently.  This function attempts to reproduce
	 * those results.
	 */
	public static String toText(double value) {
		return rawDoubleBitsToText(Double.doubleToLongBits(value));
	}
	/* package */ static String rawDoubleBitsToText(long pRawBits) {

		long rawBits = pRawBits;
		boolean isNegative = rawBits < 0; // sign bit is in the same place for long and double
		if (isNegative) {
			rawBits &= 0x7FFFFFFFFFFFFFFFL;
		}
		if (rawBits == 0) {
			return isNegative ? "-0" : "0";
		}
		ExpandedDouble ed = new ExpandedDouble(rawBits);
		if (ed.getBinaryExponent() < -1022) {
			// value is 'denormalised' which means it is less than 2^-1022
			// excel displays all these numbers as zero, even though calculations work OK
			return isNegative ? "-0" : "0";
		}
		if (ed.getBinaryExponent() == 1024) {
			// Special number NaN /Infinity
			// Normally one would not create HybridDecimal objects from these values
			// except in these cases Excel really tries to render them as if they were normal numbers
			if(rawBits == EXCEL_NAN_BITS) {
				return "3.484840871308E+308";
			}
			// This is where excel really gets it wrong
			// Special numbers like Infinity and NaN are interpreted according to
			// the standard rules below.
			isNegative = false; // except that the sign bit is ignored
		}
		NormalisedDecimal nd = ed.normaliseBaseTen();
		StringBuilder sb = new StringBuilder(MAX_TEXT_LEN+1);
		if (isNegative) {
			sb.append('-');
		}
		convertToText(sb, nd);
		return sb.toString();
	}
	private static void convertToText(StringBuilder sb, NormalisedDecimal pnd) {
		NormalisedDecimal rnd = pnd.roundUnits();
		int decExponent = rnd.getDecimalExponent();
		String decimalDigits;
		if (Math.abs(decExponent)>98) {
			decimalDigits = rnd.getSignificantDecimalDigitsLastDigitRounded();
			if (decimalDigits.length() == 16) {
				// rounding caused carry
				decExponent++;
			}
		} else {
			decimalDigits = rnd.getSignificantDecimalDigits();
		}
		int countSigDigits = countSignifantDigits(decimalDigits);
		if (decExponent < 0) {
			formatLessThanOne(sb, decimalDigits, decExponent, countSigDigits);
		} else {
			formatGreaterThanOne(sb, decimalDigits, decExponent, countSigDigits);
		}
	}

	private static void formatLessThanOne(StringBuilder sb, String decimalDigits, int decExponent,
			int countSigDigits) {
		int nLeadingZeros = -decExponent - 1;
		int normalLength = 2 + nLeadingZeros + countSigDigits; // 2 == "0.".length()

		if (needsScientificNotation(normalLength)) {
			sb.append(decimalDigits.charAt(0));
			if (countSigDigits > 1) {
    			sb.append('.');
    			sb.append(decimalDigits.subSequence(1, countSigDigits));
			}
			sb.append("E-");
			appendExp(sb, -decExponent);
			return;
		}
		sb.append("0.");
		for (int i=nLeadingZeros; i>0; i--) {
			sb.append('0');
		}
		sb.append(decimalDigits.subSequence(0, countSigDigits));
	}

	private static void formatGreaterThanOne(StringBuilder sb, String decimalDigits, int decExponent, int countSigDigits) {

		if (decExponent > 19) {
			// scientific notation
			sb.append(decimalDigits.charAt(0));
			if (countSigDigits>1) {
				sb.append('.');
				sb.append(decimalDigits.subSequence(1, countSigDigits));
			}
			sb.append("E+");
			appendExp(sb, decExponent);
			return;
		}
		int nFractionalDigits = countSigDigits - decExponent - 1;
		if (nFractionalDigits > 0) {
			sb.append(decimalDigits.subSequence(0, decExponent+1));
			sb.append('.');
			sb.append(decimalDigits.subSequence(decExponent+1, countSigDigits));
			return;
		}
		sb.append(decimalDigits.subSequence(0, countSigDigits));
		for (int i=-nFractionalDigits; i>0; i--) {
			sb.append('0');
		}
	}

	private static boolean needsScientificNotation(int nDigits) {
		return nDigits > MAX_TEXT_LEN;
	}

	private static int countSignifantDigits(String sb) {
		int result=sb.length()-1;
		while(sb.charAt(result) == '0') {
			result--;
			if(result < 0) {
				throw new RuntimeException("No non-zero digits found");
			}
		}
		return result + 1;
	}

	private static void appendExp(StringBuilder sb, int val) {
		if(val < 10) {
			sb.append('0');
			sb.append((char)('0' + val));
			return;
		}
		sb.append(val);
	}
}
