<?php class imagingsession extends baseobject {
	
	protected static array $fields=array(
			'name'=>validator::REQUIRED,
			'temperature'=>array(validator::REQUIRED, validator::INTEGER),
			'manufacturerdatabaseid'=>array(validator::REQUIRED,validator::INTEGER),
            'imagerid'=>array(validator::REQUIRED, validator::INTEGER),
			'plateid'=>array(validator::REQUIRED, validator::INTEGER),
			'imagingparametersversionid'=>array(validator::REQUIRED, validator::INTEGER),
			'imageddatetime'=>array(validator::REQUIRED, validator::DATETIME),
			'lighttype'=>validator::REQUIRED,
	);
	
	protected static array $helpTexts=array(
			'name'=>'A unique name for this plate type',
			'temperature'=>'The incubation temperature',
			'manufacturerdatabaseid'=>'The ID of this imaging session in the imager manufacturer database',
			'imagerid'=>'The imaging device used',
			'plateid'=>'The plate being imaged',
			'imagingparametersversionid'=>'The imager settings used for this imaging session',
			'imageddatetime'=>'When this imaging session happened',
			'lighttype'=>'Whether visible or UV light was used',
	);
	
	protected static string $adminSelect='SELECT SQL_CALC_FOUND_ROWS imagingsession.*, 
				plate.name AS platename, plate.description as platedescription, plate.platetypeid AS platetypeid, plate.ownerid AS plateownerid, user.fullname AS ownername,
				plate.screenid AS screenid, plate.offsetinscreenx AS offsetinscreenx, plate.offsetinscreeny AS offsetinscreeny, 
				plate.crystalscoringsystemid AS crystalscoringsystemid,
				imager.name AS imagername, imager.friendlyname AS imagerfriendlyname, 
                imager.manufacturer as imagermanufacturer, imager.manualimaging AS manualimaging,
				project.name AS projectname, project.isarchived AS isarchived
			FROM imagingsession, plate, imager, project, user
			WHERE project.id=imagingsession.projectid AND plate.id=imagingsession.plateid AND imager.id=imagingsession.imagerid AND user.id=plate.ownerid ';
	protected static string $normalSelect='SELECT SQL_CALC_FOUND_ROWS imagingsession.*, 
				plate.name AS platename, plate.description as platedescription, plate.platetypeid AS platetypeid, plate.ownerid AS plateownerid, user.fullname AS ownername,
				plate.screenid AS screenid, plate.offsetinscreenx AS offsetinscreenx, plate.offsetinscreeny AS offsetinscreeny, 
				plate.crystalscoringsystemid AS crystalscoringsystemid, 
				imager.name AS imagername, imager.friendlyname AS imagerfriendlyname, 
                imager.manufacturer as imagermanufacturer, imager.manualimaging AS manualimaging,
				project.name AS projectname, project.isarchived AS isarchived
			FROM imagingsession, plate, imager, project, user
			WHERE project.id=imagingsession.projectid AND plate.id=imagingsession.plateid AND imager.id=imagingsession.imagerid AND user.id=plate.ownerid ';
	
	protected static function getProjectClause(string $accessType, bool $forceSharedProject=false): string {
	    return ' AND ((1=1 '.database::getProjectClause($accessType,$forceSharedProject).') OR (project.isarchived=0 AND plate.ownerid='.session::getUserId().'))';
	}

	/**
	 * Creates an imaging session.
	 * @param array $request
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 * @throws NotModifiedException
	 */
	public static function create(array $request=[]): array {
		if(!isset($request['plateid'])){ throw new BadRequestException('No plate ID provided to imagingsession::create'); }
		$plate=plate::getById($request['plateid']);
		if(!$plate){ throw new BadRequestException('Could not find plate with ID '.$request['plateid']); }
		$imager=imager::getById($request['imagerid']);
		if(!$imager){ throw new BadRequestException('Could not find imager with ID '.$request['imagerid']); }
		$request['projectid']=$plate['projectid'];
		$request['temperature']=$imager['temperature'];
		if(!isset($request['imagingparametersversionid'])){
			$versions=database::queryGetAll(
					"SELECT DISTINCT imagingparametersversionid,settingvalue FROM imagingsetting WHERE settingname IN('LightPath','LightType') AND imagerid=:imagerid",
					array(':imagerid'=>$request['imagerid'])
			);
			if($versions && $versions['rows'] && 1==count($versions['rows'])){
				$request['imagingparametersversionid']=$versions['rows'][0]['imagingparametersversionid'];
				$request['lighttype']=$versions['rows'][0]['settingvalue'];
			}
		}

        $ret=parent::createByClassName($request,'imagingsession');

		if(empty($plate['firstinspectiontime'])){
			$first=database::queryGetOne('SELECT min(imageddatetime) AS first FROM imagingsession WHERE plateid=:plateid GROUP BY imageddatetime', [':plateid'=>$request['plateid']]);
			if($first){
				plate::update($plate['id'], ['firstinspectiontime'=>$first['first']]);
			}
		}

		return $ret;
	}

	public static function update(int $id, array $request=[]): array {
		if(isset($request['imagerid'])){
			$imager=imager::getById($request['imagerid']);
			$request['temperature']=$imager['temperature'];
		}
		return parent::update($id, $request);
	}

    /**
     * Creates an imaging session with dummy images.
     * @param $plateId int The ID of the parent plate
     * @return array
     * @throws BadRequestException
     * @throws NotFoundException
     * @throws ServerException
     * @throws ForbiddenException
     */
	public static function createWithDummyImages(int $plateId): array {
	    $plate=plate::getById($plateId);
	    if(!$plate){ throw new BadRequestException('Could not find plate with ID '.$plateId); }
	    
	    //copy dummy image to imagestore, if it doesn't exist
	    $imagestore=rtrim(config::get('core_imagestore'),'/').'/';
	    $dummyImageName='dummyimage.jpg';
	    $dummyThumbName='dummythumb.jpg';
	    if(!file_exists($imagestore.$dummyImageName)){
	        @copy(config::getWwwRoot().'/client/images/'.$dummyImageName, $imagestore.$dummyImageName);
	        @copy(config::getWwwRoot().'/client/images/'.$dummyThumbName, $imagestore.$dummyThumbName);
	        if(!file_exists($imagestore.$dummyImageName)){
	            throw new ServerException('Dummy drop image does not exist in image store, and could not copy it from images directory.');
	        }
	    }
	    $dimensions=@getimagesize($imagestore.$dummyImageName);
	    $imageHeight=$dimensions[1];
	    $imageWidth=$dimensions[0];
	    
	    //create dummy inspection
	    $dummyImager=imager::getByName('+20 Microscope');
	    if(!$dummyImager){
	        throw new BadRequestException('Cannot create crystal because no image was found for this drop, and cannot create a dummy image because there is no imager called +20 Microscope.');
	    }
	    $dummyInspection=imagingsession::create(array(
	        'name'=>$plate['name'].'_dummy',
	        'manufacturerdatabaseid'=>0,
	        'plateid'=>$plateId,
	        'imagerid'=>$dummyImager['id'],
	        'imageddatetime'=>gmdate('Y-m-d H:i:s')
	    ));
	    $inspectionId=$dummyInspection['created']['id'];
	    
	    //create one dummy dropimage per plate welldrop
	    $wellDrops=plate::getwelldrops($plateId);
	    foreach($wellDrops['rows'] as $wd){
    	    $imageDbName=$plate['name'].'_'.platewell::getWellLabel($wd['row'], $wd['col']).'.'.$wd['dropnumber'].'_is'.$inspectionId;
	        dropimage::create(array(
	            'name'=>$imageDbName,
	            'projectid'=>$plate['projectid'],
	            'imagingsessionid'=>$inspectionId,
	            'welldropid'=>$wd['id'],
	            'pixelheight'=>$imageHeight,
	            'pixelwidth'=>$imageWidth,
	            'micronsperpixelx'=>-1,
	            'micronsperpixely'=>-1,
	            'imagestorepath'=>$imagestore,
	            'imagepath'=>$dummyImageName,
	            'thumbnailpath'=>$dummyThumbName
	        ));
	    }
	    return $dummyInspection;
	}

	public static function getByProperty(string $key, string $value, array $request=[]): ?array {
	    if("imagermanufacturer"===$key){
            if(session::isAdmin()){
                $sqlStatement=static::$adminSelect;
            } else {
                $sqlStatement=static::$normalSelect;
            }
            $sqlStatement.=' AND imager.manufacturer<=>:val ';
            $sqlStatement.=static::getProjectClause('read');
            $sqlStatement.=database::getFilterClause($request, 'imaging');
            $sqlStatement.=database::getOrderClause($request, 'imagingsession');
            $sqlStatement.=database::getLimitClause($request);
            $params=array(':val'=>$value);
            return database::queryGetAll($sqlStatement,$params);
        }
        return parent::getByProperty($key, $value, $request);
    }

	/**
	 * Returns the drop image records for the specified imaging session.
	 * @param int $id the ID of the imaging session
	 * @param array $request The request parameters, including any pagination or sort order requirements
	 * @return array|null an array containing the drop image records
	 * @throws BadRequestException
	 * @throws ServerException
	 */
	public static function getdropimages(int $id, array $request=[]): ?array {
		return dropimage::getByProperty('imagingsessionid', $id, $request);
	}

}