<?php

use PHPUnit\Framework\TestCase;

class platereimportqueueTest extends TestCase {

    protected function setUp(): void
    {
        try {
            session::init(new DummySession());
            session::becomeAdmin();
			database::connect();
            $user = user::getFirstAdmin();
            session::set('user', $user);
            session::set('userId', $user['id']);
            config::set('reimport_enabled',1);
        } catch (BadRequestException $e) {
            echo $e->getMessage();
            $this->fail('BadRequestException on session::init');
        } catch (NotFoundException) {
            $this->fail('NotFoundException on session::init');
        } catch (ServerException) {
            $this->fail('ServerException on session::init');
        } catch (ForbiddenException) {
            $this->fail('ForbiddenException on setup - probably config::set');
        }
        database::begin();
    }

    protected function tearDown(): void {
        database::abort();
        session::destroy();
    }


    public function testGetById(){
        self::expectException('ServerException');
        self::expectExceptionMessage(platereimportqueue::GET_BY_ID_NOT_IMPLEMENTED_ON_PLATEREIMPORTQUEUE);
        platereimportqueue::getById(1);
    }

    public function testGetByName(){
        self::expectException('ServerException');
        self::expectExceptionMessage(platereimportqueue::GET_BY_NAME_NOT_IMPLEMENTED_ON_PLATEREIMPORTQUEUE);
        platereimportqueue::getByName("name");
    }

    public function testGetAll(){
        self::expectException('ServerException');
        self::expectExceptionMessage(platereimportqueue::GET_ALL_NOT_IMPLEMENTED_ON_PLATEREIMPORTQUEUE);
        platereimportqueue::getAll();
    }

    /**
     * @throws BadRequestException
     * @throws NotFoundException
     * @throws ForbiddenException
     * @throws ServerException
     */
    public function testCreate(){
        $plates=plate::getAll();
        self::assertNotEmpty($plates);
        self::assertNotEmpty($plates['rows']);
        $plate=$plates['rows'][0];
        $item=platereimportqueue::create(array('plateid'=>$plate['id']));
        self::assertNotEmpty($item);
        self::assertNotEmpty(platereimportqueue::getByPlateId($plate['id']));
    }

    /**
     * @throws BadRequestException
     * @throws NotFoundException
     * @throws ForbiddenException
     * @throws ServerException
     */
    public function testCreateDuplicate(){
        $plates=plate::getAll();
        self::assertNotEmpty($plates);
        self::assertNotEmpty($plates['rows']);
        $plate=$plates['rows'][0];
        platereimportqueue::create(array('plateid'=>$plate['id']));
        self::expectException('BadRequestException');
        self::expectExceptionMessage(platereimportqueue::PLATE_IS_ALREADY_QUEUED_FOR_RE_IMPORT);
        platereimportqueue::create(array('plateid'=>$plate['id']));
    }

    /**
     * @throws NotFoundException
     * @throws BadRequestException
     * @throws ForbiddenException
     * @throws ServerException
     */
    public function testCreateReimportDisabled(){
        $plates=plate::getAll();
        self::assertNotEmpty($plates);
        self::assertNotEmpty($plates['rows']);
        $plate=$plates['rows'][0];
        platereimportqueue::create(array('plateid'=>$plate['id']));
    }

    /**
     * @throws ServerException
     * @throws NotFoundException
     * @throws BadRequestException
     * @throws ForbiddenException
     */
    public function testGetByPlateId(){
        $plates=plate::getAll();
        self::assertNotEmpty($plates);
        self::assertNotEmpty($plates['rows']);
        $plate=$plates['rows'][0];
        platereimportqueue::create(array('plateid'=>$plate['id']));
        $item=platereimportqueue::getByPlateId($plate['id']);
        self::assertNotEmpty($item);
    }

    /**
     * @throws BadRequestException
     * @throws NotFoundException
     * @throws ServerException
     */
    public function testGetByPlateIdNoPlate(){
        $plates=plate::getAll();
        self::assertNotEmpty($plates);
        self::assertNotEmpty($plates['rows']);
        $plate=$plates['rows'][0];
        $item=platereimportqueue::getByPlateId($plate['id']);
        self::assertEmpty($item);
    }


    /**
     * @throws ForbiddenException
     * @throws BadRequestException
     * @throws ServerException
     * @throws NotFoundException
     */
    public function testDelete(){
        $plates=plate::getAll();
        self::assertNotEmpty($plates);
        self::assertNotEmpty($plates['rows']);
        $plate=$plates['rows'][0];
        $item=platereimportqueue::create(array('plateid'=>$plate['id']));
        self::assertNotEmpty($item);
        self::assertNotEmpty(platereimportqueue::getByPlateId($item['created']['plateid']));
        platereimportqueue::delete($item['created']['id']);
        self::assertEmpty(platereimportqueue::getByPlateId($item['created']['plateid']));
    }

    /**
     * @throws NotFoundException
     * @throws ForbiddenException
     * @throws BadRequestException
     * @throws ServerException
     * @throws NotModifiedException
     */
    public function testGetOldestQueueItem(){
        $queueItem=platereimportqueue::getOldestQueueItem();
        while(!empty($queueItem)){
            platereimportqueue::delete($queueItem['id']);
            $queueItem=platereimportqueue::getOldestQueueItem();
        }
        self::assertEmpty($queueItem);
        $sharedProjectId=baseproject::getSharedProjectId();
        $plateType=platetype::create(array(
            'projectid'=>$sharedProjectId,
            'name'=>'Test'.time(),
            'rows'=>8,
            'cols'=>12,
            'subs'=>3,
            'dropmapping'=>'123,RRR'
        ))['created'];
        $scoringSystem=crystalscoringsystem::create(array(
            'name'=>'Test'.time()
        ))['created'];
        foreach(['BARCODE1','A1B2C3D4','D4C3B2A1','BARCODE2'] as $barcode){
            $plate=plate::create(array(
                'name'=>$barcode,
                'ownerid'=>session::getUserId(),
                'projectid'=>$sharedProjectId,
                'platetypeid'=>$plateType['id'],
                'crystalscoringsystemid'=>$scoringSystem['id']
            ))['created'];
            platereimportqueue::create(array('plateid'=>$plate['id']));
        }
        $oldest=platereimportqueue::getOldestQueueItem();
        self::assertEquals('BARCODE1',$oldest['barcode']);
        platereimportqueue::delete($oldest['id']);
        $oldest=platereimportqueue::getOldestQueueItem();
        self::assertEquals('A1B2C3D4',$oldest['barcode']);

    }

    /**
     * @throws NotFoundException
     * @throws NotModifiedException
     * @throws BadRequestException
     * @throws ForbiddenException
     * @throws ServerException
     */
    public function testGetOldestQueueItemByPattern(){
        $sharedProjectId=baseproject::getSharedProjectId();
        $plateType=platetype::create(array(
            'projectid'=>$sharedProjectId,
            'name'=>'Test'.time(),
            'rows'=>8,
            'cols'=>12,
            'subs'=>3,
            'dropmapping'=>'123,RRR'
        ))['created'];
        $scoringSystem=crystalscoringsystem::create(array(
            'name'=>'Test'.time()
        ))['created'];
        foreach(['BARCODE1','BARCODE2','A1B2C3D4','D4C3B2A1'] as $barcode){
            $plate=plate::create(array(
                'name'=>$barcode,
                'ownerid'=>session::getUserId(),
                'projectid'=>$sharedProjectId,
                'platetypeid'=>$plateType['id'],
                'crystalscoringsystemid'=>$scoringSystem['id']
            ))['created'];
            platereimportqueue::create(array('plateid'=>$plate['id']));
        }
        $oldest=platereimportqueue::getOldestQueueItem('LLLLLLLN');
        self::assertEquals('BARCODE1',$oldest['barcode']);
        $oldest=platereimportqueue::getOldestQueueItem('LNLNLNLN');
        self::assertEquals('A1B2C3D4',$oldest['barcode']);
    }

    /**
     * @throws ServerException
     * @throws BadRequestException
     */
    public function testGetOldestQueueItemBadPattern(){
        self::expectException('ServerException');
        self::expectExceptionMessage(platereimportqueue::BAD_BARCODE_PATTERN_IN_GET_OLDEST_QUEUE_ITEM);
        platereimportqueue::getOldestQueueItem('Z');
    }

}