<?php class backgroundimage {

	private static int $THUMBNAIL_MAXHEIGHT=120;
	private static int $THUMBNAIL_MAXWIDTH=200;


	/**
	 * @throws NotFoundException
	 * @throws ServerException
	 * @throws BadRequestException
	 */
	public static function getById(int $id): void {
		static::sendBackground($id, false);
	}

	/**
	 * @throws ServerException
	 * @throws NotFoundException
	 * @throws BadRequestException
	 */
	public static function getThumb(int $id): void {
		static::sendBackground($id, true);
	}

	/**
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
	private static function sendBackground(int $id, bool $isThumb): void {
		$image=database::queryGetOne('SELECT * FROM `backgroundimage` WHERE `id`=:id',array(':id'=>$id));
		if(!$image || (!session::isAdmin() && !empty($image['userid']) && 1*$image['userid']!=session::getUserId())){
			http_response_code(404);
			exit();
		}
		$path=backgroundimage::getPathToImage($id, $isThumb);
		$file=@fopen($path,'rb');
		if(!$file){
			throw new ServerException('Could not open image file at '.$path);
		}
		header('Content-Type: '.$image['mimetype']);
		fpassthru($file);
		fclose($file);
		exit;
	}

	/**
	 * @param string $name
	 * @return mixed
	 * @throws ServerException
	 */
	public static function getByName(string $name): mixed {
		throw new ServerException('getByName not implemented on backgroundimage. Supplied name: '.$name);
	}

	/**
	 * Get all background images uploaded for common use.
	 * @return array|null
	 * @throws BadRequestException
	 * @throws ServerException
	 */
	public static function getAll(): ?array {
		return database::queryGetAll('SELECT * FROM `backgroundimage`');
	}

	/**
	 * Get all background images for a specific user.
	 * @param $key string must be 'userid'
	 * @param $value int|string The user ID
	 * @return array|null
	 * @throws BadRequestException
	 * @throws ServerException
	 */
	public static function getByProperty(string $key, int|string $value): ?array {
		if('userid'!=$key){ throw new BadRequestException('$key must be userid in backgroundimage::getByProperty'); }
		if(0===(int)$value || database::$nullValue===$value){
			$result=database::queryGetAll('SELECT * FROM `backgroundimage` WHERE userid IS NULL');
		} else {
			$result=database::queryGetAll('SELECT * FROM `backgroundimage` WHERE userid=:userid', [':userid'=>$value]);
		}
		return $result;
	}

	/**
	 * @throws BadRequestException
	 * @throws AuthorizationRequiredException
	 * @throws ServerException
	 * @throws NotFoundException
	 */
	public static function create(): array {
		if(!session::isLoggedIn()){
			throw new AuthorizationRequiredException('You must be logged in to upload background images');
		}
		$userId = session::getUserId();
		$gdAvailable=defined('GD_VERSION');
		if(!$gdAvailable){
			throw new ServerException('Cannot upload images because the GD image library is not available in PHP. Talk to your administrator.');
		}
		$file=$_FILES['image'];
		if($file['error']==1){
			throw new BadRequestException('The image could not be uploaded, probably because its file size is too big. An administrator will need to fix this.');
		}
		$info=@getimagesize($file['tmp_name']);
		if(!$info || 0==$info[0]){
			throw new BadRequestException('Uploaded file does not appear to be an image');
		}
		$pixelWidth=$info[0];
		$pixelHeight=$info[1];
		$mimeType=$info['mime'];
		if($mimeType!=='image/jpeg' && $mimeType!=='image/png'){
			throw new BadRequestException('Uploaded file does not appear to be JPEG or PNG image: ('.$mimeType.')');
		}

		if(session::isAdmin() &&isset($_POST['common'])){
			database::query('INSERT INTO backgroundimage(mimetype) VALUES(:mimetype)', [':mimetype'=>$mimeType]);
		} else {
			database::query('INSERT INTO backgroundimage(userid,mimetype) VALUES(:userid, :mimetype)', [':userid'=>$userId, ':mimetype'=>$mimeType]);
		}
		$imageId=database::getLastInsertId();
		$created=database::queryGetOne('SELECT * FROM backgroundimage WHERE id=:id',['id'=>$imageId]);

		$dir=self::getImagesDirectory($imageId);
		if(!file_exists($dir) && !mkdir($dir, 0755, true)){
			throw new ServerException('Could not create background image directory '.$dir);
		}

		$fullPath=self::getPathToImage($imageId);
		$thumbPath=self::getPathToImage($imageId,true);

		if(!@move_uploaded_file($file['tmp_name'], $fullPath)){
			throw new ServerException('Could not copy uploaded image to IceBear file store');
		}

		$thumbScale=max( ($pixelHeight/static::$THUMBNAIL_MAXHEIGHT), ($pixelWidth/static::$THUMBNAIL_MAXWIDTH) );
		$newHeight=(int)(min( $pixelHeight/$thumbScale, static::$THUMBNAIL_MAXHEIGHT));
		$newWidth=(int)(min( $pixelWidth/$thumbScale, static::$THUMBNAIL_MAXWIDTH));

		$thumb=imagecreatetruecolor($newWidth,$newHeight);
		if('image/jpeg'==$mimeType){
			$image=imagecreatefromjpeg($fullPath);
			@imagecopyresized($thumb, $image, 0, 0, 0, 0, $newWidth, $newHeight, $pixelWidth, $pixelHeight);
			imagejpeg($thumb, $thumbPath);
		} else {
			$image=imagecreatefrompng($fullPath);
			@imagecopyresized($thumb, $image, 0, 0, 0, 0, $newWidth, $newHeight, $pixelWidth, $pixelHeight);
			imagepng($thumb, $thumbPath);
		}

		if(!file_exists($thumbPath)){
			throw new ServerException('Could not write image thumbnail file');
		}


		return['created'=>$created];
	}

	/**
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ForbiddenException
	 * @throws AuthorizationRequiredException
	 * @throws ServerException
	 */
	public static function delete(int $id): array {
		if(!session::isLoggedIn()){
			throw new AuthorizationRequiredException('You must be logged in to delete background images');
		}
		$record=database::queryGetOne('SELECT * FROM backgroundimage WHERE id=:id',['id'=>$id]);
		if(!$record){ throw new NotFoundException('Image not found'); }
		$imageOwner=1*$record['userid'];
		if(!session::isAdmin() && session::getUserId() !=$imageOwner){
			throw new ForbiddenException('Image does not exist, or is not yours');
		}
		@unlink(static::getPathToImage($id,true));
		@unlink(static::getPathToImage($id));
		database::query('DELETE FROM backgroundimage WHERE id=:id',['id'=>$id]);
		database::query('DELETE FROM userconfig WHERE name="backgroundImage" AND value=:id',['id'=>$id]);
		if(session::isAdmin() && 1*config::get('core_backgroundimage_default')===$id){
			config::set('core_backgroundimage_default',0);
		}
		return ['deleted'=>$id];
	}

	/**
	 * @throws BadRequestException
	 * @throws ServerException
	 */
	public static function deleteInvalidUserConfigsAfterConfigChange(): void {
		$allow=config::get('core_backgroundimage_allow');
		if("fixed"==$allow){
			//All user background selections are invalid
			database::query('DELETE FROM userconfig WHERE name="backgroundImage"');
		} else if("select"==$allow){
			//User background selections of own images are invalid
			database::query('DELETE userconfig FROM userconfig,backgroundimage WHERE userconfig.name="backgroundImage" AND userconfig.value=CAST(backgroundimage.id AS CHAR) AND backgroundimage.userid IS NOT NULL');
		}
	}

	/**
	 * Get the full path to an image, or its thumbnail.
	 * @param int|string $imageId
	 * @param bool $toThumb
	 * @return string
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
	public static function getPathToImage(int|string $imageId, bool $toThumb=false): string {
		$imageId=intval($imageId);
		$path=static::getImagesDirectory($imageId);
		if($toThumb){ return rtrim($path,'/').'/thumb'.$imageId; }
		return rtrim($path,'/').'/image'.$imageId;
	}

	/**
	 * Get the directory where an image is stored.
	 * @param int $imageId
	 * @return string
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
	public static function getImagesDirectory(int $imageId): string {
		$image=database::queryGetOne('SELECT * FROM backgroundimage WHERE id=:id',['id'=>$imageId]);
		if(!$image){ throw new NotFoundException('Image not found'); }
		$path=rtrim(config::get('core_filestore'),'/').'/files/backgrounds/';
		if(!empty($image['userid'])){
			return $path.'user'.$image['userid'].'/';
		}
		return $path.'common/';
	}
}