/* UtilLib - Copyright (c) 2008-2015 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.format;

import java.text.ParseException;
import net.mapeadores.util.exceptions.SwitchException;


/**
 *
 * @author Vincent Calame
 */
public class Calcul {

    public final static short DIVISION = 1;
    public final static short ADDITION = 2;
    public final static short SOUSTRACTION = 3;
    public final static short MULTIPLICATION = 4;
    private final short type;
    private final boolean isEntier;
    private final int valeurEntiere;
    private final float valeur;

    Calcul(short type, float valeur) {
        this.type = type;
        this.valeur = valeur;
        isEntier = false;
        valeurEntiere = 0;
    }

    Calcul(short type, int valeurEntiere) {
        this.type = type;
        this.valeurEntiere = valeurEntiere;
        valeur = (float) valeurEntiere;
        isEntier = true;
    }

    public static Calcul parse(String s) throws ParseException {
        s = s.trim();
        if (s.length() < 2) {
            throw new ParseException("Too short", 0);
        }
        short type = 0;
        char carac = s.charAt(0);
        switch (carac) {
            case '+':
                type = ADDITION;
                break;
            case '-':
                type = SOUSTRACTION;
                break;
            case '*':
                type = MULTIPLICATION;
                break;
            case '/':
                type = DIVISION;
                break;
            default:
                throw new ParseException("Missing operator", 0);
        }
        String numero = s.substring(1).trim();
        try {
            int valeurEntiere = Integer.parseInt(numero);
            return new Calcul(type, valeurEntiere);
        } catch (NumberFormatException nfe) {
            try {
                float valeur = Float.parseFloat(numero);
                return new Calcul(type, valeur);
            } catch (NumberFormatException nfe2) {
                throw new ParseException("Not a number", 1);
            }
        }
    }

    public double execute(double d) {
        switch (type) {
            case ADDITION:
                return d + valeur;
            case SOUSTRACTION:
                return d - valeur;
            case MULTIPLICATION:
                return d * valeur;
            case DIVISION:
                return d / valeur;
            default:
                throw new SwitchException("unknwon type = " + type);
        }
    }

    public float execute(float d) {
        switch (type) {
            case ADDITION:
                return d + valeur;
            case SOUSTRACTION:
                return d - valeur;
            case MULTIPLICATION:
                return d * valeur;
            case DIVISION:
                return d / valeur;
            default:
                throw new SwitchException("unknwon type = " + type);
        }
    }

    public long execute(long l) {
        if (!isEntier) {
            return (long) execute((double) l);
        }
        switch (type) {
            case ADDITION:
                return l + valeurEntiere;
            case SOUSTRACTION:
                return l - valeurEntiere;
            case MULTIPLICATION:
                return l * valeurEntiere;
            case DIVISION:
                return l / valeurEntiere;
            default:
                throw new SwitchException("unknwon type = " + type);
        }

    }

    public int execute(int i) {
        if (!isEntier) {
            return (int) execute((float) i);
        }
        switch (type) {
            case ADDITION:
                return i + valeurEntiere;
            case SOUSTRACTION:
                return i - valeurEntiere;
            case MULTIPLICATION:
                return i * valeurEntiere;
            case DIVISION:
                return i / valeurEntiere;
            default:
                throw new SwitchException("unknwon type = " + type);
        }
    }

}
