<?php
use Carbon\Carbon;
use Illuminate\Database\Query\Builder;
use Luticate\Utils\DataAccess\LuDataAccess;
use Luticate\Utils\DataAccess\LuStoredProcedure;
use Luticate\Utils\Dbo\LuDbo;
use Luticate\Utils\Dbo\LuDboDeserializeException;
use Luticate\Utils\Dbo\LuIntDbo;
use Luticate\Utils\Dbo\LuIntDboArray;

/**
 * Created by PhpStorm.
 * User: robin
 * Date: 6/7/16
 * Time: 2:57 PM
 */

class TestTableDbo extends LuDbo
{
    /**
     * @var $_id int
     */
    private $_id;

    /**
     * @var $_someText string
     */
    private $_someText;

    /**
     * @var $_someIntegerArray int[]
     */
    private $_someIntegerArray;

    /**
     * @var $_createdAt Carbon
     */
    private $_createdAt;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->_id;
    }

    /**
     * @param int $id
     */
    public function setId($id)
    {
        $this->_id = $id;
    }

    /**
     * @return string
     */
    public function getSomeText()
    {
        return $this->_someText;
    }

    /**
     * @param string $someText
     */
    public function setSomeText($someText)
    {
        $this->_someText = $someText;
    }

    /**
     * @return int[]
     */
    public function getSomeIntegerArray()
    {
        return $this->_someIntegerArray;
    }

    /**
     * @param int[] $someIntegerArray
     */
    public function setSomeIntegerArray($someIntegerArray)
    {
        $this->_someIntegerArray = $someIntegerArray;
    }

    /**
     * @return Carbon
     */
    public function getCreatedAt()
    {
        return $this->_createdAt;
    }

    /**
     * @param Carbon $createdAt
     */
    public function setCreatedAt($createdAt)
    {
        $this->_createdAt = $createdAt;
    }

}

class TestTableDboArray extends LuDbo
{
    /**
     * @var TestTableDbo[]
     */
    protected $_array;
    public function getArray()
    {
        return $this->_array;
    }
    public function setArray($value)
    {
        $this->_array = $value;
    }

    public function jsonSerialize()
    {
        return $this->_array;
    }

    public static function jsonDeserialize($json)
    {
        if (!is_array($json)) {
            throw new LuDboDeserializeException("Invalid array value");
        }
        $dbo = new static();
        $array = [];
        foreach ($json as $data) {
            $array[] = TestTableDbo::jsonDeserialize($data);
        }
        $dbo->setArray($array);
        return $dbo;
    }

    public static function generateSample()
    {
        return [
            TestTableDbo::generateSample(),
            TestTableDbo::generateSample()
        ];
    }

}

class SpTest extends LuStoredProcedure {

    protected static $_connection = "mydb";
    protected static $_storedProcedure = "sp_test";
    protected static $_dboClass = LuIntDbo::class;

    public static function execute($an_int) {
        return self::getSingle([$an_int]);
    }

}

class SpTest2 extends LuStoredProcedure {

    protected static $_connection = "mydb";
    protected static $_storedProcedure = "sp_test2";
    protected static $_dboClass = LuIntDbo::class;
    protected static $_dboArrayClass = LuIntDboArray::class;

    public static function execute($an_int) {
        return self::getMultiple([$an_int]);
    }

    public static function executePaginated($an_int, $page, $perPage) {
        return self::getMultiplePaginated([$an_int], $page, $perPage);
    }

}

class TestTableDataAccess extends LuDataAccess
{
    protected static $_connection = "mydb";
    protected static $_table = "test_table";
    protected static $_dboClass = TestTableDbo::class;
}

class DatabaseTest extends \PHPUnit_Framework_TestCase
{
    public function testSpGetSingle()
    {
        $this->assertSame(42, LuDbo::serializeValue(SpTest::execute(42)));
    }

    public function testSpGetSingleNull()
    {
        $this->assertNull(SpTest::execute(4));
    }

    public function testSpGetMultiple()
    {
        $this->assertSame(range(0, 15), SpTest2::execute(42));
    }

    public function testSpGetMultiplePaginated1()
    {
        $this->assertSame(["count" => 16, "data" => range(0, 1)], SpTest2::executePaginated(42, 0, 2)->jsonSerialize());
    }

    public function testSpGetMultiplePaginated2()
    {
        $this->assertSame(["count" => 16, "data" => range(2, 3)], SpTest2::executePaginated(42, 1, 2)->jsonSerialize());
    }

    public function testDaGetMultiple()
    {
        $this->assertSame([["id" => 1, "someText" => "lol2", "someIntegerArray" => [], "createdAt" => "2016-06-15 13:45:23"]],
            LuDbo::serializeValue(TestTableDataAccess::getMultiple(function(Builder $q)
            {
                return $q->where("id", "=", 1);
            })));
    }

    public function testDaGetMultipleOffset()
    {
        $this->assertSame([["id" => 11, "someText" => "lol2", "someIntegerArray" => [], "createdAt" => "2016-06-15 13:45:23"]],
            LuDbo::serializeValue(TestTableDataAccess::getMultiple(function(Builder $q)
            {
                return $q->take(1)->offset(2);
            })));
    }

    public function testDaGetPaginated()
    {
        $this->assertSame(["count" => 3, "data" =>
            [["id" => 11, "someText" => "lol2", "someIntegerArray" => [], "createdAt" => "2016-06-15 13:45:23"]]],
            LuDbo::serializeValue(TestTableDataAccess::getMultiplePaginated(function(Builder $q)
            {
                return $q->orderBy("id", "ASC");
            }, 1, 1)));
    }

    public function testDaGetSingleById()
    {
        $this->assertSame(["id" => 1, "someText" => "lol2", "someIntegerArray" => [], "createdAt" => "2016-06-15 13:45:23"],
            LuDbo::serializeValue(TestTableDataAccess::getSingleById(1)));
    }
    
    public function testDatabase()
    {

//        $dbo = new TestTableDbo();
//        $dbo->setId(11);
//        $dbo->setSomeIntegerArray('{}');
//        $dbo->setSomeText("lol2");
//
//        var_dump(TestTableDataAccess::deleteMultiple(function($q)
//        {
//            return $q->where("some_text", "=", "lol");
//        }));
//        var_dump(TestTableDataAccess::addSingleId($dbo));
//        var_dump(TestTableDataAccess::addSingle($dbo, ['Id']));
//        var_dump(TestTableDataAccess::editSingleById($dbo));
//        var_dump(TestTableDataAccess::editMultiple($dbo, function($q)
//        {
//            return $q->where("some_text", "like", "lol%");
//        }, ['Id']));


//        $pdo = TestTableDataAccess::getPdo();
//        $pgsql = new PgSqlDataAccess();
//        $pgsql->getStoredProceduresFull($pdo);
//        var_dump($pgsql->getStoredProceduresFull($pdo));
    }
}