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

import java.math.BigDecimal;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.ss.format.SimpleFraction;
import org.apache.poi.ss.formula.eval.NotImplementedException;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

/**
 * <p>Format class that handles Excel style fractions, such as "# #/#" and "#/###"</p>
 *
 * <p>As of this writing, this is still not 100% accurate, but it does a reasonable job
 * of trying to mimic Excel's fraction calculations.  It does not currently
 * maintain Excel's spacing.</p>
 *
 * <p>This class relies on a method lifted nearly verbatim from org.apache.math.fraction.
 *  If further uses for Commons Math are found, we will consider adding it as a dependency.
 *  For now, we have in-lined the one method to keep things simple.</p>
 */

@SuppressWarnings("serial")
public class FractionFormat extends Format {
    private static final POILogger LOGGER = POILogFactory.getLogger(FractionFormat.class);
    private static final Pattern DENOM_FORMAT_PATTERN = Pattern.compile("(?:(#+)|(\\d+))");

    //this was chosen to match the earlier limitation of max denom power
    //it can be expanded to get closer to Excel's calculations
    //with custom formats # #/#########
    //but as of this writing, the numerators and denominators
    //with formats of that nature on very small values were quite
    //far from Excel's calculations
    private static final int MAX_DENOM_POW = 4;

    //there are two options:
    //a) an exact denominator is specified in the formatString
    //b) the maximum denominator can be calculated from the formatString
    private final int exactDenom;
    private final int maxDenom;

    private final String wholePartFormatString;

    /**
     * Single parameter ctor
     * @param denomFormatString The format string for the denominator
     */
    public FractionFormat(String wholePartFormatString, String denomFormatString) {
        this.wholePartFormatString = wholePartFormatString;

        // initialize exactDenom and maxDenom
        Matcher m = DENOM_FORMAT_PATTERN.matcher(denomFormatString);
        int tmpExact = -1;
        int tmpMax = -1;
        if (m.find()){
            if (m.group(2) != null){
                try{
                    tmpExact = Integer.parseInt(m.group(2));
                    //if the denom is 0, fall back to the default: tmpExact=100

                    if (tmpExact == 0){
                        tmpExact = -1;
                    }
                } catch (NumberFormatException e){
                    // should not happen because the pattern already verifies that this is a number,
                    // but a number larger than Integer.MAX_VALUE can cause it,
                    // so throw an exception if we somehow end up here
                    throw new IllegalStateException(e);
                }
            } else if (m.group(1) != null) {
                int len = m.group(1).length();
                len = len > MAX_DENOM_POW ? MAX_DENOM_POW : len;
                tmpMax = (int)Math.pow(10, len);
            } else {
                tmpExact = 100;
            }
        }
        if (tmpExact <= 0 && tmpMax <= 0){
            //use 100 as the default denom if something went horribly wrong
            tmpExact = 100;
        }
        exactDenom = tmpExact;
        maxDenom = tmpMax;
    }

    @SuppressWarnings("squid:S2111")
    public String format(Number num) {

        final BigDecimal doubleValue = new BigDecimal(num.doubleValue());

        final boolean isNeg = doubleValue.compareTo(BigDecimal.ZERO) < 0;

        final BigDecimal absValue = doubleValue.abs();
        final BigDecimal wholePart = new BigDecimal(absValue.toBigInteger());
        final BigDecimal decPart = absValue.remainder(BigDecimal.ONE);

        if (wholePart.add(decPart).compareTo(BigDecimal.ZERO) == 0) {
            return "0";
        }

        // if the absolute value is smaller than 1 over the exact or maxDenom
        // you can stop here and return "0"
        // reciprocal is result of an int devision ... and so it's nearly always 0
        // double reciprocal = 1/Math.max(exactDenom,  maxDenom);
        // if (absDoubleValue < reciprocal) {
        //    return "0";
        // }

        //this is necessary to prevent overflow in the maxDenom calculation
        if (decPart.compareTo(BigDecimal.ZERO) == 0){

            StringBuilder sb = new StringBuilder();
            if (isNeg){
                sb.append("-");
            }
            sb.append(wholePart);
            return sb.toString();
        }

        final SimpleFraction fract;
        try {
            //this should be the case because of the constructor
            if (exactDenom > 0){
                fract = SimpleFraction.buildFractionExactDenominator(decPart.doubleValue(), exactDenom);
            } else {
                fract = SimpleFraction.buildFractionMaxDenominator(decPart.doubleValue(), maxDenom);
            }
        } catch (RuntimeException e){
            LOGGER.log(POILogger.WARN, "Can't format fraction", e);
            return Double.toString(doubleValue.doubleValue());
        }

        StringBuilder sb = new StringBuilder();

        //now format the results
        if (isNeg){
            sb.append("-");
        }

        //if whole part has to go into the numerator
        if (wholePartFormatString == null || wholePartFormatString.isEmpty()){
            final int fden = fract.getDenominator();
            final int fnum = fract.getNumerator();
            BigDecimal trueNum = wholePart.multiply(new BigDecimal(fden)).add(new BigDecimal(fnum));
            sb.append(trueNum.toBigInteger()).append("/").append(fden);
            return sb.toString();
        }


        //short circuit if fraction is 0 or 1
        if (fract.getNumerator() == 0){
            sb.append(wholePart);
            return sb.toString();
        } else if (fract.getNumerator() == fract.getDenominator()){
            sb.append(wholePart.add(BigDecimal.ONE));
            return sb.toString();
        }
       //as mentioned above, this ignores the exact space formatting in Excel
        if (wholePart.compareTo(BigDecimal.ZERO) > 0){
            sb.append(wholePart).append(" ");
        }
        sb.append(fract.getNumerator()).append("/").append(fract.getDenominator());
        return sb.toString();
    }

    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
        return toAppendTo.append(format((Number)obj));
    }

    public Object parseObject(String source, ParsePosition pos) {
        throw new NotImplementedException("Reverse parsing not supported");
    }

}
