#!/usr/bin/env snip

sample_image = image_new [
    $pixel => Vector [1, 2, 3],
    $interpretation => Interpretation.sRGB
] 1 1;

Base_enum = class Enum {
    A = 1;
    B = 2;

    _extra = 99;
}

Derived_enum = class Base_enum {
    C = 3;
    D = 4;

    _extra = 100;
}

main = unit_test [
    [(Group [1, 2]).value == [1, 2], "Group construct"],
    [(Group [1, 2] + 2).value == [3, 4], "Group add"],
    [(Group [1, 2] == Group [1, 2]).value == [true, true], "Group equal"],
    [(if Group [true, false] then Group [1, 2] else Group [3, 4]).value ==
        [1, 4],
            "Group ifthenelse"],

    [(Real 12).value == 12, "Real construct"],
    [(Real 12 + 1).value == 13, "Real add"],
    [Real 12 + 1 == Real 13, "Real equal"],

    [(Bool true).value == true, "Bool construct"],
    [(!Bool true).value == false, "not Bool"],
    [!Bool true == false, "Bool equal"],

    [(Vector [1, 2, 3]).value == [1, 2, 3], "Vector construct"],
    [(Vector [1, 2, 3] + 1).value == [2, 3, 4], "Vector add"],
    [Vector [1, 2, 3] + 1 == Vector [2, 3, 4], "Vector equal"],
    [is_image (sample_image + Vector [1, 2, 3]), "image + Vector is image"],
    [is_Image (Image sample_image + Vector [1, 2, 3]),
        "Image + Vector is Image"],
    [mean(sample_image + Vector [1, 2, 3]) == mean (Vector [2, 4, 6]),
        "image + Vector"],
    [mean(Image sample_image + Vector [1, 2, 3]) == mean (Vector [2, 4, 6]),
        "Image + Vector"],

    [Base_enum.keys == ["A", "B"], "base enum keys"],
    [Base_enum.values == [1, 2], "base enum keys"],
    [Derived_enum.keys == ["A", "B", "C", "D"], "derived enum keys"],
    [Derived_enum.values == [1, 2, 3, 4], "derived enum keys"],
    [Derived_enum.keys?(Derived_enum.get_index_from_key "B") == "B",
        "derived enum index"],

    [(Matrix [[1, 2], [3, 4]]).value == [[1, 2], [3, 4]], "Matrix construct"],
    [(Matrix [[1, 2], [3, 4]] + 1).value == [[2, 3], [4, 5]],
        "Matrix scalar add"],
    [Matrix [[1, 2], [3, 4]] + 1 == Matrix [[2, 3], [4, 5]],
        "Matrix equal"],
    [Matrix [[1, 2], [3, 4]] ** -1 == Matrix [[-2, 1], [1.5, -0.5]],
        "Matrix invert"],
    [Matrix [[1, 2], [3, 4]] * Matrix [[2, 3], [4, 5]] ==
        Matrix [[10, 13], [22, 29]],
            "Matrix multiply"],

    [(Colour "sRGB" [255, 255, 255]).value == [255, 255, 255],
        "Colour construct"],
    [(Colour "sRGB" [255, 255, 255] - 255).value == [0, 0, 0],
        "Colour scalar subtract"],
    [(Colour "sRGB" [255, 255, 255] - Vector [1, 2, 3]).value == [254, 253,252],
        "Colour vector subtract"],
    [(Colour "sRGB" [255, 255, 255] - Colour "sRGB" [1, 2, 3]).value ==
        [254, 253, 252],
            "Colour subtract"],
    [Colour "sRGB" [255, 255, 255] - Colour "sRGB" [1, 2, 3] ==
        Colour "sRGB" [254, 253, 252],
            "equal Colour Colour"],
    [is_Image (Image sample_image + Colour "sRGB" [10, 0, 0]),
        "add Colour Image is Image"],
    [is_image (sample_image + Colour "sRGB" [10, 0, 0]),
        "add Colour image is image"],
    [to_colour (sample_image + Colour "sRGB" [10, 0, 0])
        == Colour "sRGB" [11, 2, 3],
            "add Colour Image"],

    [!(Rect 10 20 30 40).is_empty, "Rect construct"],
    [Rect 10 20 30 40 == Rect 10 20 30 40, "Rect equal"],
    [Rect 10 20 30 40 + 10 == Rect 20 30 40 50, "Rect scalar add"],
    [(Rect 10 20 30 40).includes_point 15 25, "Rect includes point"],
    [Rect 10 20 30 40 >= Rect 10 20 30 40, "Rect includes rect"],
    [!(Rect 10 20 30 40 > Rect 10 20 30 40), "Rect includes not equal rect"],
    [Rect 0 0 100 100 > Rect 10 20 30 40, "Rect includes not equal rect"],
    [Rect 10 20 30 40 + Rect 10 20 30 50 == Rect 10 20 30 50,
        "Rect union"],
    [Rect 10 20 30 40 * Rect 10 20 10 10 == Rect 10 20 10 10,
        "Rect intersect"],
    [(Rect 10 20 30 40).margin_adjust 2 == Rect 8 18 34 44, "Rect margin"],

    // ++ on lists is lazy in both args
    [take 4 ([1..] ++ [2..]) == [1..4], "++ lazy in first list arg"],
    [take 4 ([1, 2, 3] ++ [2..]) == [1, 2, 3, 2], "++ lazy in second list arg"],
    [take 4 ([] ++ [2..]) == [2..5], "++ lazy in second list arg 2"],

    // ++ on Image does bandjoin
    [point (0, 0) (Image sample_image ++ 4) == Vector [1, 2, 3, 4],
        "Image ++ real"],
    [point (0, 0) (Image sample_image ++ [4]) == Vector [1, 2, 3, 4],
        "Image ++ [real]"],
    [point (0, 0) (Image sample_image ++ Real 4) == Vector [1, 2, 3, 4],
        "Image ++ Real"],
    [point (0, 0) (Image sample_image ++ Vector [4]) == Vector [1, 2, 3, 4],
        "Image ++ Vector"],

    [point (0, 0) (sample_image ++ 4) == [1, 2, 3, 4],
        "image ++ real"],
    [point (0, 0) (sample_image ++ [4]) == [1, 2, 3, 4],
        "image ++ [real]"],
    [point (0, 0) (sample_image ++ Real 4) == [1, 2, 3, 4],
        "image ++ Real"],
    [point (0, 0) (sample_image ++ Vector [4]) == [1, 2, 3, 4],
        "image ++ Vector"],

    [point (0, 0) (4 ++ Image sample_image) == Vector [4, 1, 2, 3],
        "real ++ Image"],
    // [4] ++ Image can't work since ++ is lazy in the first list arg
    [point (0, 0) (Real 4 ++ Image sample_image) == Vector [4, 1, 2, 3],
        "Real ++ Image"],
    [point (0, 0) (Vector [4] ++ Image sample_image) == Vector [4, 1, 2, 3],
        "Vector ++ Image"],

    // add more! from Image onwards

    [(List [1, 2]).value == [1, 2], "List construct"],
    [(List [1, 2] + 2).value == [3, 4], "List add scalar"],
    [List [1, 2] + 2 == List [3, 4], "List add scalar equal"],
    [List [1, 2] + List [3, 4] == List [4, 6], "List add vector"],
    [2 + List [1, 2] == List [3, 4], "scalar add List equal"],
    [hd (List [1, 2]) == 1, "List hd"],
    [tl (List [1]) == [], "List tl"],
    // can't overload `:`, sadly
    [List [] == [], "List [] == []"]

];
