package io.parsingdata.metal;

import io.parsingdata.metal.data.Environment;
import io.parsingdata.metal.data.ParseGraph;
import io.parsingdata.metal.data.ParseResult;
import io.parsingdata.metal.token.Token;
import org.junit.Test;

import java.io.IOException;

import static io.parsingdata.metal.Shorthand.*;
import static io.parsingdata.metal.util.EncodingFactory.enc;
import static io.parsingdata.metal.util.EnvironmentFactory.stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class SubStructTableTest {

    private final Token struct =
        seq(def("header", con(1), eq(con(42))),
            def("footer", con(1), eq(con(84))));

    private final Token table =
        seq(def("tableSize", con(1)),
            repn(def("pointer", con(1)), ref("tableSize")),
            sub(struct, ref("pointer")));

    @Test
    public void table() throws IOException {
        final Environment env = stream(3, 6, 4, 9, 42, 84, 42, 84, 0, 42, 84);
                            /* offset: 0, 1, 2, 3,  4,  5,  6,  7, 8,  9, 10
                             * count:  ^
                             * pointers:  ^, ^, ^
                             * ref1:      +----------------^^--^^
                             * ref2:         +-----^^--^^
                             * ref3:            +---------------------^^--^^
                             */
        final ParseResult res = table.parse(env, enc());
        assertTrue(res.succeeded());
        assertEquals(4, res.getEnvironment().offset);
        final ParseGraph order = res.getEnvironment().order;
        checkStruct(order.head.asGraph().head.asGraph());
        checkStruct(order.head.asGraph().head.asGraph().tail);
        checkStruct(order.head.asGraph().head.asGraph().tail.tail);
    }

    @Test
    public void tableWithDuplicate() throws IOException {
        final Environment env = stream(4, 7, 5, 5, 10, 42, 84, 42, 84, 0, 42, 84);
                            /* offset: 0, 1, 2, 3,  4,  5,  6,  7, 8,  9, 10, 11
                             * count:  ^
                             * pointers:  ^, ^, ^, ^^
                             * ref1:      +--------------------^^--^^
                             * ref2:         +---------^^--^^
                             * ref3:         +---------^^--^^ duplicate!
                             * ref4:               ++---------------------^^--^^
                             */
        final ParseResult res = table.parse(env, enc());
        assertTrue(res.succeeded());
        assertEquals(5, res.getEnvironment().offset);
        final ParseGraph order = res.getEnvironment().order;
        checkStruct(order.head.asGraph().head.asGraph());
        assertTrue(order.head.asGraph().head.asGraph().tail.head.isRef());
        //checkStruct(order.head.asGraph().head.asGraph().tail.head.asRef().resolve(order));
        checkStruct(order.head.asGraph().head.asGraph().tail.tail);
        checkStruct(order.head.asGraph().head.asGraph().tail.tail.tail);
    }

    private void checkStruct(final ParseGraph graph) {
        assertEquals(84, graph.head.asGraph().head.asValue().asNumeric().intValue());
        assertEquals(42, graph.head.asGraph().tail.head.asValue().asNumeric().intValue());
    }

}

@@ -1650,32 +1650,47 @@
 ).head.asGraph()
+.head.asGraph()
 );%0A        check
@@ -1732,24 +1732,39 @@
 Graph().tail
+.head.asGraph()
 );%0A        c
@@ -1811,32 +1811,47 @@
 raph().tail.tail
+.head.asGraph()
 );%0A    %7D%0A%0A    @T
@@ -2745,32 +2745,47 @@
 ).head.asGraph()
+.head.asGraph()
 );%0A        asser
@@ -2858,10 +2858,8 @@
     
-//
 chec
@@ -2998,24 +2998,39 @@
 ().tail.tail
+.head.asGraph()
 );%0A        c
@@ -3090,16 +3090,31 @@
 ail.tail
+.head.asGraph()
 );%0A    %7D
@@ -3206,31 +3206,16 @@
 ph.head.
-asGraph().head.
 asValue(
@@ -3272,31 +3272,16 @@
 , graph.
-head.asGraph().
 tail.hea

Test for Sub list semantics with pointertable with duplicates.