<?php
/**
 * @filename StringReaderTest.php
 * @author Jerry Yan <792602257@qq.com>
 * @date 2020/12/18 12:19
 */

namespace JerryYan\DSL\Test\Reader;

use JerryYan\DSL\Reader\StringReader;
use PHPUnit\Framework\TestCase;

class StringReaderTest extends TestCase
{
    protected $readerWithCrLf;
    protected $readerWithCn;
    protected $reader;
    protected function setUp(): void
    {
        $this->reader = new StringReader(" Ahhh  This Is 一个 新的 TOken");
        $this->readerWithCn = new StringReader(" 中文  这是 Is 一个 新的 TOken");
        $this->readerWithCrLf = new StringReader(" 中文 \r\n\r 这是 \r Is \n 一个 新的 TOken");
    }

    public function testGetNextChar()
    {
        $this->reader->reset();
        $this->assertEquals('A', $this->reader->getNextChar(), "不匹配");
        $this->assertEquals(1, $this->reader->getCurrentPosition(), "CurPos与预计不符");
        $this->readerWithCn->reset();
        $this->assertEquals('中', $this->readerWithCn->getNextChar(), "不匹配");
        $this->assertEquals(1, $this->readerWithCn->getCurrentPosition(), "CurPos与预计不符");
    }

    public function testGetCurrentToken()
    {
        $this->reader->reset();
        $this->assertEquals('Ahhh', $this->reader->getCurrentToken(), "不匹配");
        $this->assertEquals(6, $this->reader->getNextPosition(), "NextPos与预计不符");
        $this->readerWithCn->reset();
        $this->assertEquals('中文', $this->readerWithCn->getCurrentToken(), "不匹配");
        $this->assertEquals(4, $this->readerWithCn->getNextPosition(), "NextPos与预计不符");
    }

    /**
     * 移动至下一个Token
     * @author Jerry Yan <792602257@qq.com>
     * @date 2020/12/18 14:16
     * @depends testGetNextChar
     * @depends testGetCurrentToken
     * @depends testGetNextToken
     */
    public function testMoveToNextToken()
    {
        $this->reader->reset();
        $oldCurToken = $this->reader->getCurrentToken();
        $oldNextPos = $this->reader->getNextPosition();
        $oldNextToken = $this->reader->getNextToken();
        $this->reader->moveToNextToken();
        $this->assertNotEquals($oldCurToken, $this->reader->getCurrentPosition(), "CurToken与旧CurToken相同");
        $this->assertNotEquals($oldNextPos, $this->reader->getNextPosition(), "NextPos与旧NextPos相同");
        $this->assertEquals($oldNextToken, $this->reader->getCurrentToken(), "不匹配");
        $this->assertEquals(7, $this->reader->getCurrentPosition(), "CurPos与预计不符");
        $this->assertNotEquals($this->reader->getNextPosition(), $this->reader->getCurrentPosition(), "CurPos与NextPos相同");
        // CJK Support
        $this->readerWithCn->reset();
        $oldCurTokenCn = $this->readerWithCn->getCurrentToken();
        $oldNextPosCn = $this->readerWithCn->getNextPosition();
        $oldNextTokenCn = $this->readerWithCn->getNextToken();
        $this->readerWithCn->moveToNextToken();
        $this->assertNotEquals($oldCurTokenCn, $this->readerWithCn->getCurrentPosition(), "CurToken与旧CurToken相同");
        $this->assertNotEquals($oldNextPosCn, $this->readerWithCn->getNextPosition(), "NextPos与旧NextPos相同");
        $this->assertEquals($oldNextTokenCn, $this->readerWithCn->getCurrentToken(), "不匹配");
        $this->assertEquals(5, $this->readerWithCn->getCurrentPosition(), "CurPos与预计不符");
    }

    /**
     * 获取下一个Token,重复调用均为同一结果
     * @author Jerry Yan <792602257@qq.com>
     * @date 2020/12/18 18:49
     */
    public function testGetNextToken()
    {
        $this->reader->reset();
        $curPos = $this->readerWithCn->getCurrentPosition();
        $nextPos = $this->reader->getNextPosition();
        $string = $this->reader->getNextToken();
        $this->assertEquals($string, $this->reader->getNextToken(), "不匹配");
        $this->assertEquals($this->reader->getNextToken(), $this->reader->getNextToken(), "不匹配");
        $this->assertEquals($curPos, $this->reader->getCurrentPosition(), "CurPos不可以发生变化");
        $this->assertEquals($nextPos, $this->reader->getNextPosition(), "NextPos不可以发生变化");
    }

    public function testSkipCurrentLine()
    {
        $this->readerWithCrLf->resetCursor();
        $this->readerWithCrLf->skipCurrentLine();
        // moveToNextToken又移动了
        $this->assertEquals(3, $this->readerWithCrLf->getCurrentLine(), "行号不匹配");
        $this->assertEquals(1, $this->readerWithCrLf->getCurrentLinePosition(), "CLPos不匹配");
        $this->assertEquals("这是", $this->readerWithCrLf->getCurrentToken(), "Token不匹配");
        $this->assertEquals(8, $this->readerWithCrLf->getCurrentPosition(), "CurPos不匹配");
        $this->readerWithCrLf->skipCurrentLine();
        $this->assertEquals(4, $this->readerWithCrLf->getCurrentLine(), "行号不匹配");
        $this->assertEquals(1, $this->readerWithCrLf->getCurrentLinePosition(), "CLPos不匹配");
        $this->assertEquals("Is", $this->readerWithCrLf->getCurrentToken(), "Token不匹配");
        $this->assertEquals(13, $this->readerWithCrLf->getCurrentPosition(), "CurPos不匹配");
        $this->readerWithCrLf->skipCurrentLine();
        $this->assertEquals(5, $this->readerWithCrLf->getCurrentLine(), "行号不匹配");
        $this->assertEquals(1, $this->readerWithCrLf->getCurrentLinePosition(), "CLPos不匹配");
        $this->assertEquals("一个", $this->readerWithCrLf->getCurrentToken(), "Token不匹配");
        $this->assertEquals(18, $this->readerWithCrLf->getCurrentPosition(), "CurPos不匹配");
    }

    public function testResetCursor()
    {
        $this->reader->moveToNextToken();
        $curPos = $this->reader->getCurrentPosition();
        $nextPos = $this->reader->getNextPosition();
        $string = $this->reader->getCurrentToken();
        $this->reader->resetCursor();
        $this->assertNotEquals($curPos, $this->reader->getCurrentPosition(), "CurPos未发生变化");
        $this->assertNotEquals($nextPos, $this->reader->getNextPosition(), "NextPos未发生变化");
        $this->assertNotEquals($string, $this->reader->getCurrentToken(), "CurToken未发生变化");
    }
}