<?php class PlateImport extends Device {

    const USERNAME='plateimporter';
    const USERFULLNAME='Plate Importer';
    const PLATETYPE_DIMENSIONS_MISMATCH_MESSAGE='Plate type already exists (found by name) but dimensions do not match';
    const USER_BAD_EMAIL_MESSAGE='Email address is invalid';
    const SCORING_SYSTEM_NOT_FOUND_MESSAGE='No scoring system found with that name';
    const BAD_SEQUENCE_MESSAGE='Supplied sequence is not a valid DNA or protein sequence';
    const PROJECT_FOR_PROTEIN_ALREADY_EXISTS_MESSAGE = 'Project for this protein already exists';
    const ONLY_ONE_CONSTRUCT_PER_PLATE_MESSAGE = 'Multiple proteins/constructs per plate not supported';
    const NO_PLATE_WITH_BARCODE_MESSAGE = 'No plate with that barcode';
    const BAD_LIGHT_TYPE_MESSAGE = 'Only "UV" and "Visible" accepted as lightType';
    const BAD_DATE_MESSAGE = 'Bad date, should be a UTC date in YYYY-MM-DD hh:mm:ss';
    const NO_IMAGER_WITH_NAME_MESSAGE = 'No imager with that name';

    public static function getVersion(): int {
        return 1;
    }

	/**
	 * @param array $plateType
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function createPlateType(array $plateType): array {
        Log::debug('In PlateImport::createPlateType');
        foreach($plateType as $k=>$v){
            Log::debug('- '.$k.'='.$v);
        }
        static::require(['name','rows'], $plateType);
        static::requireOneOf(['columns','cols'], $plateType);
        static::requireOneOf(['subPositions','subpositions','subs'], $plateType);
        if(isset($plateType['subpositions'])){ $plateType['subPositions']=$plateType['subpositions']; }
        if(isset($plateType['subs'])){ $plateType['subPositions']=$plateType['subs']; }
        if(isset($plateType['cols'])){ $plateType['columns']=$plateType['cols']; }
        $existingPlateType=platetype::getByName($plateType['name']);
        if($existingPlateType) {
            Log::info('Plate type exists');
            if($existingPlateType['rows']!=$plateType['rows'] || $existingPlateType['cols']!=$plateType['columns'] || $existingPlateType['subs']!=$plateType['subPositions']){
                throw new BadRequestException(PlateImport::PLATETYPE_DIMENSIONS_MISMATCH_MESSAGE);
            }
            //"Duplicate" breaks PowerShell image push. Don't reinstate. If this breaks WIS import, fix it there.
            //$existingPlateType['dropMapping']=$existingPlateType['dropmapping'];
            $existingPlateType['receiversId']=$existingPlateType['id'];
            Log::debug('Returning from PlateImport::createPlateType');
            return $existingPlateType;
        }
        Log::info('Plate type does not exist. Creating...');
        session::becomeAdmin();
        $sharedProject = project::getByName(baseproject::SHARED);
        if (!$sharedProject) {
            throw new NotFoundException('No project called ' . baseproject::SHARED);
        }
        $dropMapping = array('', '');
        for ($i = 1; $i <= $plateType['subPositions']; $i++) {
            $dropMapping[0] .= $i;
            $dropMapping[1] .= 'R';
        }
        $dropMapping = implode(',', $dropMapping);
        platetype::create(array(
            'name' => $plateType['name'],
            'projectid' => $sharedProject['id'],
            'rows' => $plateType['rows'],
            'cols' => $plateType['columns'],
            'subs' => $plateType['subPositions'],
            'dropmapping' => $dropMapping
        ));
        Log::info('...created.');
        $plateType=platetype::getByName($plateType['name']);
		if(!$plateType){
			throw new ServerException('Created plate type, but could not find it with getByName() after');
		}
        //"Duplicate" breaks PowerShell image push. Don't reinstate. If this breaks WIS import, fix it there.
        //$plateType['dropMapping']=$plateType['dropmapping'];
        $plateType['receiversId']=$plateType['id'];
        Log::debug('Returning from PlateImport::createPlateType');
        return $plateType;
    }

	/**
	 * @param array $user
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function createUser(array $user): array {
        Log::debug('In PlateImport::createUser');
        $user=UserManagement::createUser($user);
        Log::debug('Returning from PlateImport::createUser');
        return $user;
    }

	/**
	 * Creates an imager, or finds an existing one, and returns the supplied parameters with the imager ID in receiversId.
	 * @param array $imager
	 * @return array
	 * @throws BadRequestException if nominalTemperature is not numeric, or if plateCapacity is not an integer greater than 0.
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException if imager already exists but temperature or capacity do not match
	 */
    public static function createImager(array $imager): array {
        Log::debug('In PlateImport::createImager');
        $imager=ImagingManagement::createImager($imager);
        Log::debug('Returning from PlateImport::createImager');
        return $imager;
    }

	/**
	 * @param array $params
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function createScoringSystem(array $params): array {
        Log::debug('In PlateImport::createScoringSystem');
        $system=ImageScoring::createScoringSystem($params);
        Log::debug('Returning from PlateImport::createScoringSystem');
        return $system;
    }

	/**
	 * @param array $params
	 * @return array
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function getScoringSystem(array $params): array {
        Log::debug('In PlateImport::getScoringSystem');
        $system=ImageScoring::getScoringSystem($params);
        Log::debug('Returning from PlateImport::getScoringSystem');
        return $system;
    }

	/**
	 * @param array $proteins
	 * @param int $projectOwnerId
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function createMultipleProteins(array $proteins, int $projectOwnerId): array {
        Log::debug('In PlateImport::createMultipleProteins');
        foreach ($proteins as &$protein) {
            $protein=static::createProteinAndConstructs($protein, $projectOwnerId);
        }
        Log::debug('Returning from PlateImport::createMultipleProteins');
        return $proteins;
    }

    /**
     * Finds the project and protein with a matching name, creating if necessary.
     * @return array $protein but with receiversId populated for protein and construct(s)
     * @param $protein array The supplied protein/construct/sequence hierarchy
     * @param $projectOwnerId int The owner of the project (only used if project does not exist)
     * @throws BadRequestException
     * @throws ServerException
     * @throws NotFoundException
     * @throws ForbiddenException
     */
    public static function createProteinAndConstructs(array $protein, int $projectOwnerId): array {
        Log::debug('In PlateImport::createProteinAndConstructs');
        static::require(['name','constructs'], $protein);
        session::becomeAdmin();

        //try to find existing project, which will have our protein in it. If it exists, don't create.
        $proteinName=$protein['name'];
	    $project=project::getByName($proteinName);
        if(!$project){
            $project=project::create(array(
                'name'=>$proteinName,
                'description'=>'Generated by plate import',
                'owner'=>$projectOwnerId
            ));
			$project=$project['created'];
        }
        $projectId=$project['id'];
		session::becomeAdmin();

        $existingProtein=protein::getByProperties(array(
            'name'=>$proteinName,
            'projectid'=>$projectId
        ));
        if($existingProtein){
            $existingProtein=$existingProtein['rows'][0];
        } else {
            $proteinAcronym='';
            if(isset($protein['proteinAcronym'])){
                $proteinAcronym=$protein['proteinAcronym'];
            }
            $existingProtein=protein::create(array(
                'name'=>$protein['name'],
                'description'=>$protein['name'],
                'projectid'=>$projectId,
                'proteinacronym'=>$proteinAcronym
            ))['created'];
            //"Full length" construct is created by default. Get rid of it.
            $unneededConstructs=protein::getconstructs($existingProtein['id']);
            if(!empty($unneededConstructs)){
                foreach ($unneededConstructs['rows'] as $unneededConstruct){
                    construct::delete($unneededConstruct['id']);
                }
            }
        }
        $proteinId=$existingProtein['id'];
        $protein['receiversId']=$proteinId;

        foreach($protein['constructs'] as &$construct) {
            $existingConstruct = construct::getByProperties(array(
                'name' => $construct['name'],
                'proteinid' => $proteinId
            ));
            if ($existingConstruct) {
                $existingConstruct = $existingConstruct['rows'][0];
            } else {
                $description = $construct['name'];
                if (isset($construct['description'])) {
                    $description = $construct['description'];
                }
                $existingConstruct = construct::create(array(
                    'name' => $construct['name'],
                    'description' => $description,
                    'owner' => $projectOwnerId,
                    'proteinid' => $proteinId
                ))['created'];
            }

            $constructId = $existingConstruct['id'];
            $construct['receiversId'] = $constructId;

            $existingSequences = construct::getsequences($constructId);
            if (isset($existingSequences['rows'])) {
                $existingSequences = $existingSequences['rows'];
            }
            $newSequences=[];
            if(isset($construct['sequences'])){
                $newSequences = $construct['sequences'];
            }

            if (empty($existingSequences) && empty($newSequences)) {
                $sequencesMatch = true;
            } else if (empty($existingSequences) && !empty($newSequences)) {
                $sequencesMatch = false;
            } else if (!empty($existingSequences) && empty($newSequences)) {
                $sequencesMatch = false;
            } else if (count($existingSequences) != count($newSequences)) {
                $sequencesMatch = false;
            } else {
                $sequencesMatch = true;
                for ($i = 0; $i < count($newSequences); $i++) {
                    $newSequence = $newSequences[$i];
                    $existingSequence = $existingSequences[$i];
                    $newSequence = preg_replace('/[^A-Z]/', '', strtoupper($newSequence));
                    $existingProteinSequence = preg_replace('/[^A-Z]/', '', strtoupper($existingSequence['proteinsequence']));
                    $existingDnaSequence = preg_replace('/[^A-Z]/', '', strtoupper($existingSequence['dnasequence']));
                    if ($newSequence !== $existingDnaSequence && $newSequence !== $existingProteinSequence) {
                        $sequencesMatch = false;
                        break;
                    }
                }
            }

            if (!$sequencesMatch) {
                //First delete the existing sequences
                if (!empty($existingSequences)) {
                    foreach ($existingSequences as $existingSequence) {
                        sequence::delete($existingSequence['id']);
                    }
                }
                //Now create with the new information
                if (!empty($newSequences)) {
                    $count = 1;
                    foreach ($newSequences as $newSequence) {
                        $toCreate = array(
                            'name' => 'Sequence ' . $count,
                            'constructid' => $constructId
                        );
                        if (validator::isValid($newSequence, validator::DNASEQUENCE)) {
                            $toCreate['dnasequence'] = $newSequence;
                            $toCreate['proteinsequence'] = sequence::dnaToProtein($newSequence);
                        } else if (validator::isValid($newSequence, validator::PROTEINSEQUENCE)) {
                            $toCreate['dnasequence'] = '';
                            $toCreate['proteinsequence'] = $newSequence;
                        } else {
                            throw new BadRequestException(static::BAD_SEQUENCE_MESSAGE);
                        }
                        sequence::create($toCreate);
                        $count++;
                    }
                }
            }
        }
        session::revertAdmin();
        Log::debug('Returning from PlateImport::createProteinAndConstructs');
        return $protein;
    }

	/**
	 * @param array $plate
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws NotModifiedException
	 * @throws ServerException
	 */
    public static function createPlate(array $plate): array {
        Log::debug('In PlateImport::createPlate');
        static::require(['barcode','scoringSystemName','plateType','owner'],$plate);
        session::becomeAdmin();
        $barcode=$plate['barcode'];
        $existingPlate=plate::getByName($barcode);
        if($existingPlate){
            Log::info("Plate $barcode exists");
            $plate['receiversId']=$existingPlate['id'];
            $plate['plateType']=PlateImport::createPlateType($plate['plateType']);
            $plate['owner']=PlateImport::createUser($plate['owner']);
            $plate['created']=0;
        } else {
            Log::info("Plate $barcode does not exist");
            $scoringSystem=PlateImport::getScoringSystem(array('name'=>$plate['scoringSystemName']));
            if(!$scoringSystem){
                session::revertAdmin();
                throw new NotFoundException('No scoring system called '.$plate['scoringSystemName'].'. Create it in IceBear.');
            }
			$projectId = $plate['projectId'] ?? $plate['projectid'] ?? static::getDefaultProjectId();

			Log::debug('Creating/getting plate type');
            $plate['plateType']=PlateImport::createPlateType($plate['plateType']);
			Log::debug('Creating/getting plate owner');
            $plate['owner']=PlateImport::createUser($plate['owner']);
			Log::debug('Calling plate::create');
			$newPlate=plate::create(array(
                'name'=>$barcode,
                'ownerid'=>$plate['owner']['receiversId'],
                'projectid'=>$projectId,
                'platetypeid'=>$plate['plateType']['receiversId'],
                'crystalscoringsystemid'=>$scoringSystem['receiversId']
            ));
			if(!$newPlate || !$newPlate['created']){ throw new ServerException('Could not create plate'); }
			$newPlate=$newPlate['created'];
            $plate['receiversId']=$newPlate['id'];
            $plate['created']=1;

            if(isset($plate['screenId'])){
                plate::update($plate['receiversId'], ['screenid'=>$plate['screenId']]);
            } else if(isset($plate['screenid'])){
                plate::update($plate['receiversId'], ['screenid'=>$plate['screenid']]);
            }

            if(isset($plate['description'])){
                plate::update($plate['receiversId'], ['description'=>$plate['description']]);
            }

        }

        if(!empty($plate['proteins'])){
            if(count($plate['proteins'])!==1 || count($plate['proteins'][0]['constructs'])!==1){
                throw new ServerException(self::ONLY_ONE_CONSTRUCT_PER_PLATE_MESSAGE);
            }
            $plate['proteins']=PlateImport::createMultipleProteins($plate['proteins'], $plate['owner']['receiversId']);
            plate::update($plate['receiversId'], array(
                'constructid'=>$plate['proteins'][0]['constructs'][0]['receiversId']
            ));
        }
        session::revertAdmin();

        if(isset($plate['imageBatches'])){
            foreach ($plate['imageBatches'] as &$imagingSession){
                $imagingSession['plateBarcode']=$barcode;
                $imagingSession=PlateImport::createImageBatch($imagingSession);
                unset($imagingSession['plateBarcode']);
            }
        }

        $plate['id']=$plate['receiversId'];
        $plate['name']=$plate['barcode'];
        Log::debug('Returning from PlateImport::createPlate');
        return $plate;
    }

	/**
	 * @param array $imageBatch
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function createImageBatch(array $imageBatch): array {
        static::require(['dateTimeUtc','plateBarcode','lightType','imagerName'],$imageBatch);
        try {
            session::becomeAdmin();
            $dateTime=$imageBatch['dateTimeUtc'];
            $dateTime=DateTime::createFromFormat('Y-m-d H:i:s', $dateTime, new DateTimeZone('UTC'));
            if(!$dateTime){
                throw new BadRequestException(self::BAD_DATE_MESSAGE);
            }

            //Ensure the imager already exists
            $imagerName=$imageBatch['imagerName'];
            $imager=imager::getByName($imagerName);
            if(!$imager) {
                throw new NotFoundException(self::NO_IMAGER_WITH_NAME_MESSAGE);
            }
            $imagerId=$imager['id'];

            //Ensure the plate already exists
            $barcode=$imageBatch['plateBarcode'];
            $plate=plate::getByName($barcode);
            if(!$plate) {
                throw new NotFoundException(self::NO_PLATE_WITH_BARCODE_MESSAGE);
            }
            $plateId=$plate['id'];

            //subtract 1 second from imaged time for UV images, to separate from visible
            $lightType=$imageBatch['lightType'];
            if(!in_array($lightType, array('UV', 'Visible'))){
                throw new BadRequestException(self::BAD_LIGHT_TYPE_MESSAGE);
            }
            if('UV'===$lightType){
                $dateTime->sub(new DateInterval('PT1S'));
            }

            $existingImagingSession=imagingsession::getByProperties(array(
                'imageddatetime'=>$dateTime->format('Y-m-d H:i:s'),
                'plateid'=>$plateId,
                'lighttype'=>$lightType
            ));
            if($existingImagingSession){
                $existingImagingSession=$existingImagingSession['rows'][0];
            } else {
                $sendersId=0;
                if(isset($imageBatch['sendersId'])){
                    $sendersId=$imageBatch['sendersId'];
                }

                $imagingParametersName=$imagerName.'_'.$lightType;
                $imagingParametersVersionName=$imagingParametersName.'_v1';
                $imagingParametersVersion=imagingparametersversion::getByName($imagingParametersVersionName);
                if(!$imagingParametersVersion){
                    $sharedProjectid=static::getSharedProjectId();
                    $imagingParameters=imagingparameters::getByName($imagingParametersName);
                    if(!$imagingParameters){
                        $imagingParameters=imagingparameters::create(array(
                            'name'=>$imagingParametersName,
                            'manufacturer'=>$imager['manufacturer'],
                            'manufacturerdatabaseid'=>0,
                            'projectid'=>$sharedProjectid
                        ))['created'];
                    }
                    $imagingParametersVersion=imagingparametersversion::create(array(
                        'name'=>$imagingParametersVersionName,
                        'projectid'=>$sharedProjectid,
                        'manufacturerdatabaseid'=>0,
                        'imagingparametersid'=>$imagingParameters['id']
                    ))['created'];
                }
                $imagingParametersVersionId=$imagingParametersVersion['id'];
                $existingImagingSession=imagingsession::create(array(
                    'name'=>$barcode.'_'.$lightType.'_'.$dateTime->format('Y-m-d H:i:s'),
                    'plateid'=>$plateId,
                    'lighttype'=>$lightType,
                    'imageddatetime'=>$dateTime->format('Y-m-d H:i:s'),
                    'imagerid'=>$imagerId,
                    'manufacturerdatabaseid'=>$sendersId,
                    'imagingparametersversionid'=>$imagingParametersVersionId
                ))['created'];
            }

            $imageBatch['receiversId']=$existingImagingSession['id'];

            if(isset($imageBatch['images'])){
                foreach ($imageBatch['images'] as &$image) {
                    $image['iceBearImagingSessionId']=$imageBatch['receiversId'];
                    $image=PlateImport::createImage($image);
                    unset($image['iceBearImagingSessionId']);
                    $image['imageData']='(trimmed)';
                    $image['thumbData']='(trimmed)';
                }
            }

        } finally {
            session::revertAdmin();
        }
        return $imageBatch;
    }

	/**
	 * @param array $image
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function createImage(array $image): array {
        Log::debug('In PlateImport::createImage');
        $image=ImagingManagement::createImage($image);
        Log::debug('Returning from PlateImport::createImage');
        return $image;
    }

	/**
	 * @param array $params
	 * @return array
	 * @throws BadRequestException
	 * @throws ServerException
	 */
    public static function getScreenByName(array $params): array {
        Log::debug('In PlateImport::getScreenByName');
        static::require('name', $params);
        session::becomeAdmin();
        $screen=screen::getByName($params['name']);
        if(!$screen){
            Log::info('Screen does not exist: '.$params['name']);
            Log::debug('Returning from PlateImport::getScreenByName');
            return [];
        }
        $conditions=screen::getscreenconditions($screen['id'], ['all'=>1]);
        if(!$conditions){
            Log::warning('Screen has no conditions');
        } else {
            if(isset($conditions['rows'])){
                $conditions=$conditions['rows'];
            }
            $screen['conditions']=$conditions;
        }
        session::revertAdmin();
        Log::debug('Returning from PlateImport::getScreenByName');
        return $screen;
    }

	/**
	 * @param array $params
	 * @return ?array
	 * @throws BadRequestException
	 * @throws ServerException
	 */
    public static function getProjectByName(array $params): ?array {
        Log::debug('In PlateImport::getProjectByName');
        static::require('name', $params);
        session::becomeAdmin();

		$project=project::getByName($params['name']);
		if(!$project){
			Log::info('No project called '.$params['name']);
			Log::debug('Returning from PlateImport::getProjectByName');
		}
		Log::debug('Returning from PlateImport::getProjectByName');
		return $project;
    }

	/**
	 * @param array $params
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 */
    public static function createProject(array $params): array {
        Log::debug('In PlateImport::createProject');
        static::require(['name','ownerId','description'], $params);
        session::becomeAdmin();
        Log::info('Creating project'.$params['name']);
        $project=project::create([
            'name'=>$params['name'],
            'owner'=>$params['ownerId'],
            'description'=>$params['description']
        ])['created'];
        Log::info('Created project');
        Log::debug('Returning from PlateImport::createProject');
        return $project;
    }

    /**
     * @param $params
     * @return array
     * @throws BadRequestException
     * @throws ForbiddenException
     * @throws NotFoundException
     * @throws NotModifiedException
     * @throws ServerException
     *
     * {
     *   "name":"Helsinki Complex",
     *   "projectId":2,
     *   "isStandard":false,
     *   "conditions":[
     *     {
     *       "wellNumber":1,
     *       "description":"Buffer: 0.1M tris hydrochloride, pH 8; Polymer: 25v/v polyethylene glycol 300",
     *       "descriptionNoRoles":"0.1M tris hydrochloride, pH 8; 25v/v polyethylene glycol 300",
     *       "components":[
     *         {
     *           "concentration":0.1,
     *           "unit":"M",
     *           "name":"tris hydrochloride",
     *           "role":"Buffer",
     *           "pH":8,
     *           "description":"Buffer: 0.1M tris hydrochloride, pH 8",
     *           "descriptionNoRoles":"0.1M tris hydrochloride, pH 8"
     *         },
     *         {...}
     *       ]
     *     }
     *   ]
     * }
     */
    public static function createScreen(array $params): array {
        session::becomeAdmin();
        static::require(['name','rows','cols','conditions','projectId'], $params);
        if(empty($params['conditions'])){
            throw new BadRequestException('Screen has no conditions');
        }
        $name=$params['name'];
        $existing=screen::getByName($name);
        if($existing){ return $existing; }
        $rows=$params['rows'];
        $cols=$params['cols'];
        $projectId=$params['projectId'];
        $isStandard=(isset($params['isStandard']) && !!$params['isStandard']);
        $screen=screen::create([
            'name'=>$name,
            'rows'=>$rows,
            'cols'=>$cols,
            'projectid'=>$projectId,
            'isstandard'=>$isStandard
        ])['created'];
        $screenId=$screen['id'];
        foreach ($params['conditions'] as $condition){
            static::require(['wellNumber','components','description','descriptionNoRoles'], $condition);
            $wellNumber=$condition['wellNumber'];
            $description=$condition['description'];
            $descriptionNoRoles=$condition['descriptionNoRoles'];
            Log::debug("Condition in well $wellNumber is $descriptionNoRoles");
            //$components=$condition['components'];
            //TODO Later store components in database, not just description
            $dummyCondition=screencondition::getByProperties([
                'screenid'=>$screenId,
                'wellnumber'=>$wellNumber
            ]);
            if(!$dummyCondition){
                throw new NotFoundException("No dummy condition exists for screen $screenId well number $wellNumber");
            }
            if(1!==count($dummyCondition['rows'])){
                throw new ServerException("More than one condition exists for screen $screenId well number $wellNumber");
            }
            $dummyCondition=$dummyCondition['rows'][0];
            $dummyConditionId=$dummyCondition['id'];
            screencondition::update($dummyConditionId,['description'=>$descriptionNoRoles]);
        }
        $screen=screen::getById($screenId);
        $conditions=screen::getscreenconditions($screenId);
        if(!isset($conditions['rows'])){
            throw new NotFoundException('Screen has no conditions');
        }
        $screen['conditions']=$conditions['rows'];
        return $screen;
    }

    /**
     * @param $params
     * @return array
     * @throws BadRequestException
     * @throws ForbiddenException
     * @throws NotFoundException
     * @throws ServerException
     */
    public static function getPlateForReimport(array $params): array {
        $pattern='';
        if(isset($params['imagerType'])){
            if('formulatrix'==strtolower($params['imagerType'])){
                $pattern=FormulatrixImport::BARCODE_PATTERN;
            } else if('rigaku'==strtolower($params['imagerType'])){
                $pattern=RigakuImport::BARCODE_PATTERN;
            }
        }
        session::becomeAdmin();
        $plate=array();
        $item=platereimportqueue::getOldestQueueItem($pattern);
        if(!empty($item)){
            $plate=plate::getById($item['plateid']);
            $plate['barcode']=$plate['name'];
            platereimportqueue::delete($item['id']);
        }
        return $plate;

    }

}
