<?php class diffractionrequest extends baseobject { 
	
	protected static array $fields=array(
		'name'=>validator::REQUIRED,
		'crystalid'=>array(validator::REQUIRED, validator::INTEGER),
		'shipmentid'=>validator::INTEGER,
	    'crystalidatremotefacility'=>validator::ANY,
	    'crystalurlatremotefacility'=>validator::ANY,
	    'diffractiontype'=>validator::ANY,
	    'observedresolution'=>validator::FLOAT,
	    'requiredresolution'=>validator::FLOAT,
	    'minimumresolution'=>validator::FLOAT,
	    'actiononreturn'=>validator::ANY,
	    'comment'=>validator::ANY,
	);
	
	protected static array $helpTexts=array(
		'name'=>'The name of the shipment destination',
		'crystalid'=>'The ID of the crystal to which this comment relates',
		'shipmentid'=>'The ID of the shipment - crystal may be shipped several times with different comments',
	    'crystalidatremotefacility'=>'The ID of the crystal in the remote facility database',
	    'crystalurlatremotefacility'=>'The URL of the crystal at the remote facility',
	    'diffractiontype'=>'',
	    'observedresolution'=>'',
	    'requiredresolution'=>'',
	    'minimumresolution'=>'',
	    'actiononreturn'=>'Whether to keep or wash the associated crystal/pin on return',
	    'comment'=>'Free-text comments',
	);
	
	const KEEP_CRYSTAL='keep';
	const WASH_CRYSTAL='wash';
	
	public static function create(array $request=[]): array {
		$crystal=crystal::getById($request['crystalid']);
		$request['projectid']=$crystal['projectid'];
		$request['name']='crystal'.$crystal['id'].'_diffreq_'.microtime();
		
		//Doing this in code, not as a database default, in case non-ISPyB synchrotrons require changes later
		$request['diffractiontype']='OSC';
		
		return parent::create($request);
	}

	/**
	 * @param int $id
	 * @param array $request
	 * @return array
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
	public static function update(int $id, array $request=[]): array {
	    $diffractionRequest=static::getById($id);
	    if(!$diffractionRequest){ throw new NotFoundException('No diffractionrequest with ID '.$id); }
	    if(isset($request['shipmentid'])){
	        //Crystal has been shipped. We need to update the shipmentid, but also create
	        //a new diffractionrequest for any subsequent shipments of the same crystal.
	        database::query(
	            'UPDATE diffractionrequest set shipmentid=:sid WHERE id=:id',
	            array(':id'=>$id, ':sid'=>$request['shipmentid'])
	        );
            $newDiffractionRequest=database::queryGetOne(
                'SELECT * FROM diffractionrequest WHERE crystalid=:cid AND shipmentid IS NULL',
                array(':cid'=>$diffractionRequest['crystalid'])
            );
            if(!$newDiffractionRequest){
                $wasAdmin=session::isAdmin();
                session::set('isAdmin', true);
                $newDiffractionRequest=static::create(array(
                    'diffractiontype'=>'OSC', //Doing this in code, not as a database default, in case non-ISPyB synchrotrons require changes later
                    'crystalid'=>$diffractionRequest['crystalid']
                ));
                $newDiffractionRequest=$newDiffractionRequest['created'];
                if(!empty($diffractionRequest['observedresolution'])){
                    static::update($newDiffractionRequest['id'], array('observedresolution'=>$diffractionRequest['observedresolution']));
                }
                session::set('isAdmin', $wasAdmin);
            }
	    }
	    return parent::update($id, $request);
	}

	/**
	 * @param int $id
	 * @return array|null
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
	public static function getById(int $id): ?array {
        $dr=parent::getById($id);
        if(!$dr && session::isShipper()){
            try {
                session::becomeAdmin();
                $dr=parent::getById($id);
                session::revertAdmin();
            } catch (Exception $e){
                session::revertAdmin();
                throw $e;
            }
        }
        return $dr;
    }

	/**
	 * @param int $id
	 * @return bool
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public static function canUpdate(int $id): bool {
	    return parent::canUpdate($id) || session::isShipper();
    }


}