/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import Parser.ConstList;
import Parser.IConstList;
import Parser.ILexicalAnalyzer;
import Parser.IReservedWords;
import Parser.ISource;
import Parser.ISymbolTable;
import Parser.LexicalAnalyzer;
import Parser.ReservedWords;
import Parser.StringSource;
import Parser.SymbolTable;
import Parser.Token;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author SCHETTINO
 */
public class LogoLexicalAnalyzerTest {

    private IReservedWords rws;
    private ISymbolTable st;
    private IConstList<Integer> nums;

    public LogoLexicalAnalyzerTest() {
    }

    @BeforeClass
    public static void setUpClass() {
    }

    @AfterClass
    public static void tearDownClass() {
    }

    @Before
    public void setUp() {
        rws = new ReservedWords();
        st = new SymbolTable();
        nums = new ConstList<Integer>();
    }

    @After
    public void tearDown() {
    }

    @Test
    public void nextTokenEmptyTest() {
        String[] string = {""};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token token = la.nextToken();
        Token expectedToken = Token.EOF;
        assertEquals(expectedToken, token);
    }

    @Test
    public void nextTokenOneCommandTest() {
        String[] string = {"clearscreen"};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.CLEARSCREEN;
        assertEquals(expectedToken, la.nextToken());
    }

    @Test
    public void nextTokenOneCommandWithParameterTest() {
        int number = 30;
        String[] string = {"forward " + number};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.FORWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        int i = 0;
        assertEquals(expectedToken, la.nextToken());
        assertEquals(number, nums.getConst(i++).intValue());
    }

    @Test
    public void nextTokenOneCommandWithCommaTest() {
        int number = 30;
        String[] string = {"forward " + number + ";"};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.FORWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        int i = 0;
        assertEquals(number, nums.getConst(i++).intValue());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
    }

    @Test
    public void nextTokenTwoCommandsTest() {
        int number = 30;
        int number2 = 40;
        String[] string = {"forward " + number + ";backward " + number2};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.FORWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        int i = 0;
        assertEquals(number, nums.getConst(i++).intValue());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.BACKWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        assertEquals(number2, nums.getConst(i++).intValue());
        expectedToken = Token.EOF;
        assertEquals(expectedToken, la.nextToken());
    }

    @Test
    public void nextTokenToCommandTest() {
        String id = "square";
        String[] string = {"to " + id + " {", "forward 30;", "right 90;", "};"};

        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.TO;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.ID;
        assertEquals(expectedToken, la.nextToken());
        int i = 0;
        assertEquals(id, st.searchSymbol(i));
        expectedToken = Token.LEFT_BRACES;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.FORWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.RIGHT;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.RIGHT_BRACES;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.EOF;
        assertEquals(expectedToken, la.nextToken());
    }

    @Test
    public void nextTokenFunctionInceptionTest() {
        int number = 4;
        String id = "square";
        String[] string = {"to " + id + " { repeat " + number + " {clearscreen;};};"};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.TO;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.ID;
        assertEquals(expectedToken, la.nextToken());
        int i = 0;
        assertEquals(id, st.searchSymbol(i));
        expectedToken = Token.LEFT_BRACES;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.REPEAT;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        assertEquals(number, nums.getConst(i++).intValue());
        expectedToken = Token.LEFT_BRACES;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.CLEARSCREEN;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.RIGHT_BRACES;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.RIGHT_BRACES;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.EOF;
        assertEquals(expectedToken, la.nextToken());
    }

    @Test
    public void nextTokenCommentLineTest() {
        String[] string = {"//forward 50;", "backward 20"};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.BACKWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.EOF;
        assertEquals(expectedToken, la.nextToken());
    }

    @Test
    public void nextTokenCommentLineOnLastLineTest() {
        String[] string = {"backward 20", "//forward 50;"};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.BACKWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.EOF;
        assertEquals(expectedToken, la.nextToken());
    }

    @Test
    public void nextTokenTwoCommentsInARollTest() {
        String[] string = {"backward 20", "//forward 50;", "//forward 50;", "clearscreen;"};
        ISource source = new StringSource(string);
        ILexicalAnalyzer la = new LexicalAnalyzer(source, rws, nums, st);

        Token expectedToken = Token.BACKWARD;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.NUM;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.CLEARSCREEN;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.SEMI_COMMA;
        assertEquals(expectedToken, la.nextToken());
        expectedToken = Token.EOF;
        assertEquals(expectedToken, la.nextToken());
    }
}