package org.nwapw.abacus.tests;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.nwapw.abacus.Abacus;
import org.nwapw.abacus.config.Configuration;
import org.nwapw.abacus.number.NumberInterface;
import org.nwapw.abacus.plugin.StandardPlugin;
import org.nwapw.abacus.tree.TreeNode;

public class CalculationTests {

    private static Abacus abacus = new Abacus(new Configuration(0, "precise", new String[]{}));

    @BeforeClass
    public static void prepareTests(){
        abacus.getPluginManager().addInstantiated(new StandardPlugin(abacus.getPluginManager()));
        abacus.getPluginManager().load();
    }

    private void testOutput(String input, String parseOutput, String output){
        TreeNode parsedTree = abacus.parseString(input);
        Assert.assertNotNull(parsedTree);
        Assert.assertEquals(parsedTree.toString(), parseOutput);
        NumberInterface result = abacus.evaluateTree(parsedTree);
        Assert.assertNotNull(result);
        Assert.assertTrue(result.toString().startsWith(output));
    }

    private void testEvalError(String input, String parseOutput){
        TreeNode parsedTree = abacus.parseString(input);
        Assert.assertNotNull(parsedTree);
        Assert.assertEquals(parsedTree.toString(), parseOutput);
        Assert.assertNull(abacus.evaluateTree(parsedTree));
    }

    @Test
    public void testAddition(){
        testOutput("9.5+10", "(9.5+10)", "19.5");
    }

    @Test
    public void testSubtraction(){
        testOutput("9.5-10", "(9.5-10)", "-0.5");
    }

    @Test
    public void testMultiplication(){
        testOutput("9.5*10", "(9.5*10)", "95");
    }

    @Test
    public void testDivision(){
        testOutput("9.5/2", "(9.5/2)", "4.75");
    }

    @Test
    public void testNegation(){
        testOutput("-9.5", "(9.5)`", "-9.5");
    }

    @Test
    public void testFactorial(){
        testOutput("7!", "(7)!", "5040");
    }

    @Test
    public void testAbs(){
        testOutput("abs(-1)", "abs((1)`)", "1");
        testOutput("abs(1)", "abs(1)", "1");
    }

    @Test
    public void testLn(){
        testEvalError("ln(-1)", "ln((1)`)");
        testOutput("ln2", "ln(2)", "0.6931471805599453094172321214581765680755");
    }

    @Test
    public void testSqrt(){
        testOutput("sqrt0", "sqrt(0)", "0");
        testOutput("sqrt4", "sqrt(4)", "2");
        testOutput("sqrt2", "sqrt(2)", "1.4142135623730950488016887242096980785696");
    }

    @Test
    public void testExp(){
        testOutput("exp0", "exp(0)", "1");
        testOutput("exp1", "exp(1)", "2.718281828459045235360287471352662497757247");
        testOutput("exp300", "exp(300)", "1.9424263952412559365842088360176992193662086");
        testOutput("exp(-500)", "exp((500)`)", "7.1245764067412855315491573771227552469277568");
    }

    @Test
    public void testPow(){
        testOutput("0^2", "(0^2)", "0");
        testOutput("2^0", "(2^0)", "1");
        testOutput("2^1", "(2^1)", "2");
        testOutput("2^-1", "(2^(1)`)", "0.5");
        testOutput("2^50", "(2^50)", "112589990684262");
    }

}

@@ -3103,21 +3103,214 @@
 90684262%22);%0A
+        testOutput(%227%5E(-sqrt2*17)%22, %22(7%5E((sqrt(2)*17))%60)%22, %224.81354609155297814551845300063563%22);%0A        testEvalError(%220%5E0%22, %22(0%5E0)%22);%0A        testEvalError(%22(-13)%5E.9999%22, %22((13)%60%5E0.9999)%22);%0A
     %7D%0A%0A%7D%0A

Add some tests to pow.