import uk.me.nxg.unity.*;

import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;

public class TestDimensions {

    private static Dimensions d1;
    private static Dimensions d2;
    private static Dimensions d3;

    // Return all of the dimensions of a Dimensions object, as an array, for testing
    private float[] getDimensionsAsArray(Dimensions d) {
        float f[] = new float[7];
        f[0] = d.exponent(Dimensions.BaseQuantity.LENGTH);
        f[1] = d.exponent(Dimensions.BaseQuantity.MASS);
        f[2] = d.exponent(Dimensions.BaseQuantity.TIME);
        f[3] = d.exponent(Dimensions.BaseQuantity.CURRENT);
        f[4] = d.exponent(Dimensions.BaseQuantity.TEMPERATURE);
        f[5] = d.exponent(Dimensions.BaseQuantity.AMOUNT);
        f[6] = d.exponent(Dimensions.BaseQuantity.LUMINOUSINTENSITY);
        return f;
    }

    static {
        try {
            // includes theta (here just to test UTF-8 happiness
            d1 = Dimensions.parse("L^-1 M-0.5 T^3 Θ ");
            // lots of space and other junk, including a U which should be ignored
            d2 = Dimensions.parse("  U L  .+1 M T^*-2 ");
            // trailing letter (ie no following number, indicating a power of 1)
            d3 = Dimensions.parse("L2MT2I");
        } catch (UnitParserException e) {
            System.err.println("Can't initialise!: " + e);
        }
    }

    @Test public void testSimpleParse() throws Exception {
        float f1[] = { -1, (float)-0.5,  3,  0, 1, 0, 0 };
        float f2[] = { +1,         1,   -2,  0, 0, 0, 0 };
        float f3[] = { +2,         1,    2,  1, 0, 0, 0 };
        assertArrayEquals("parse1", f1, getDimensionsAsArray(d1), (float)0.0);
        assertArrayEquals("parse2", f2, getDimensionsAsArray(d2), (float)0.0);
        assertArrayEquals("parse3", f3, getDimensionsAsArray(d3), (float)0.0);
    }

    // Note: the method Dimensions.exponents() does the same as the
    // test function getDimensionsAsArray().  It's been deprecated,
    // since it ties us to a specific representation of the exponents.
    // But we should still test it, until it's eventually removed.
    @SuppressWarnings("deprecation")
    @Test public void testSimpleParseDeprecated() throws Exception {
        float f1[] = { -1, (float)-0.5,  3,  0, 1, 0, 0 };
        float f2[] = { +1,         1,   -2,  0, 0, 0, 0 };
        float f3[] = { +2,         1,    2,  1, 0, 0, 0 };
        assertArrayEquals("parse1", f1, d1.exponents(), (float)0.0);
        assertArrayEquals("parse2", f2, d2.exponents(), (float)0.0);
        assertArrayEquals("parse3", f3, d3.exponents(), (float)0.0);
    }

    @Test public void testMultiplication2() throws Exception {
        Dimensions d12 = d1.multiply(d2);
        float f[] = { 0, (float)+0.5, 1, 0, 1, 0, 0 };
        assertArrayEquals("multiply2", f, getDimensionsAsArray(d12), (float)0.0);
    }

    @Test public void testMultiplicationMany() throws Exception {
        java.util.List<Dimensions> l = new java.util.ArrayList<Dimensions>();
        l.add(d1);
        l.add(d2);
        l.add(d3);

        Dimensions dn = Dimensions.multiply(l);
        float f[] = { 2, (float)+1.5, 3, 1, 1, 0, 0 };

        assertArrayEquals("multiplySeveral", f, getDimensionsAsArray(dn), (float)0.0);
    }

    @Test public void testMultiplicationWithNull() throws Exception {
        java.util.List<Dimensions> l = new java.util.ArrayList<Dimensions>();
        l.add(d1);
        l.add(null);
        l.add(d3);

        // the following shouldn't fail, but should return null without error
        assertNull(Dimensions.multiply(l));
    }

    @Test public void testURLs() throws Exception {
        String base = "http://qudt.org/vocab/dimension#Dimension_SI_";

        assertEquals("URI1", base+"L-1M-0.5T3Θ", d1.getURI());
        assertEquals("URI2", base+"LMT-2", d2.getURI());
        assertEquals("URI3", base+"L2MT2I", d3.getURI());
    }

    @Test(expected=UnitParserException.class) public void testFails1() throws Exception {
        Dimensions.parse("L1 1"); // number without preceding letter
    }
    @Test(expected=UnitParserException.class) public void testFails2() throws Exception {
        Dimensions.parse("L1A1"); // bad uppercase letter
    }
    @Test(expected=UnitParserException.class) public void testFails3() throws Exception {
        Dimensions.parse("l1"); // lowercase letter
    }

    public static void main(String args[]) {
        org.junit.runner.JUnitCore.main("TestDimensions");
    }
}
