<?php 

class config {
	
	private static array $fields=array(
			'name'=>validator::REQUIRED,
			'description'=>validator::REQUIRED,
			'type'=>validator::REQUIRED,
			'enumvalues'=>validator::ANY,
			'minimum'=>validator::FLOAT,
			'maximum'=>validator::FLOAT,
			'defaultvalue'=>validator::ANY,
			'value'=>validator::ANY,
	);
	
	private static array $helpTexts=array(
			'name'=>'The field name',
			'description'=>'Short description of the field',
			'type'=>'string, enum, etc.',
			'enumvalues'=>'A list of values',
			'minimum'=>'For numeric values, the minimum',
			'maximum'=>'For numeric values, the maximum',
			'defaultvalue'=>'The default value of the field',
			'value'=>'The current value',
	);
	
	public static function getFieldValidations(): array {
		return self::$fields;
	}
	public static function getFieldHelpTexts(): array {
		return self::$helpTexts;
	}
	
	public static function canCreate(): bool {
		return session::isAdmin();
	}

	/**
	 * @param int $id
	 * @return bool
	 */
    public static function canUpdate(int $id): bool {
		return session::isAdmin();
	}

	/**
	 * @throws ServerException
	 * @throws BadRequestException
	 */
	static function get(string $name): ?string {
		$result=database::queryGetOne('SELECT value FROM config WHERE name=:name', array(':name'=>$name));
		if(!$result){ return null; }
		return trim($result['value']);
	}

	/**
	 * @param string $name
	 * @param string $value
	 * @return bool
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 */
	public static function set(string $name, string $value): bool {
		if(!session::isAdmin()){ throw new ForbiddenException('Only administrators can see or change the configuration'); }
		$item=database::queryGetOne('SELECT * FROM config WHERE name=:name', array(':name'=>$name));
		if(!$item){ throw new BadRequestException('No config item called '.$name); }
		//TODO Validate!
		database::query('UPDATE config SET value=:value WHERE name=:name', array(':name'=>$name, ':value'=>trim($value)));
		if('core_backgroundimage_allow'==$name){
			backgroundimage::deleteInvalidUserConfigsAfterConfigChange();
		}
		return true;
	}

    /**
     * @param array $request
     * @return array|null
     * @throws ForbiddenException
	 * @throws ServerException
	 * @throws BadRequestException
     * @noinspection PhpUnusedParameterInspection
     */
	public static function getAll(array $request=[]): ?array{
		if(!session::isAdmin()){ throw new ForbiddenException('Only administrators can see the configuration'); }
		$result=database::queryGetAll('SELECT * FROM config ORDER BY name ');
		if(!$result){ return null; }
		return $result;
	}

	/**
	 * @param int $id
	 * @throws BadRequestException
	 */
	static function getById(int $id): ?array {
		throw new BadRequestException('getById not implemented on config');
	}

	/**
	 * @param string $name
	 * @throws BadRequestException
	 */
	static function getByName(string $name): ?array {
		throw new BadRequestException('getByName not implemented on config');
	}

	/**
	 * @param string $key
	 * @param string $value
	 * @param array $request
	 * @throws BadRequestException
	 * @noinspection PhpUnusedParameterInspection
	 */
	static function getByProperty(string $key, string $value, array $request=[]): ?array {
		throw new BadRequestException('getByProperty not implemented on config');
	}

	/**
	 * @param $keyValuePairs
	 * @param array $request
	 * @return array|null
	 * @throws BadRequestException
	 */
	static function getByProperties($keyValuePairs, array $request=array()): ?array {
		throw new BadRequestException('getByProperties not implemented on config');
	}

	/**
     * Returns the IceBear document root (the full path of the directory above api and client), without trailing slash.
     * @return string
     */
    public static function getWwwRoot(): string {
        return rtrim(dirname(__DIR__, 2),'/');
    }

    /**
     * Whether this looks like an IceBox managed IceBear installation.
     * @return bool
     */
    public static function isIceBox(): bool {
        $isIceBox=null;
        $sessionExists=session::exists();
        if($sessionExists){
            $isIceBox=session::get('isIceBox');
        }
		if(is_null($isIceBox) && isset($_SERVER['HTTP_HOST'])){
			$iceBoxHostname='.icebox.icebear.fi';
			if(str_ends_with(rtrim($_SERVER['HTTP_HOST'], '/'), $iceBoxHostname)){
				$isIceBox=true;
				session::set('isIceBox', true);
			}
		}
        if(is_null($isIceBox)) {
            $isIceBox = file_exists(config::getWwwRoot().'/isIceBox');
            if($sessionExists){
                session::set('isIceBox', $isIceBox);
            }
        }
        return $isIceBox;
    }

	/**
	 * Returns the unique subdomain part ZZZZ for a given IceBox installation, if installed at /var/www/icebear-ZZZZZ,
	 * otherwise returns false. This is used in the storage mount, the www-root, the database name, etc.
	 * @return string|null
	 */
    public static function getIceBoxName(): ?string {
        $iceBoxName=null;
        $sessionExists=session::exists();
        if($sessionExists){
            $iceBoxName=session::get('iceBoxName');
        }
		if(is_null($iceBoxName) && isset($_SERVER['HTTP_HOST'])){
			$host=$_SERVER['HTTP_HOST'];
			$domain='.icebox.icebear.fi';
			if(str_ends_with($host,$domain)){
				$name=str_replace($domain,'',$host);
				if(preg_match('/^[a-z0-9_-]+$/', $name)){
					$iceBoxName=$name;
				}
			}

		}
        if(is_null($iceBoxName)){
            if(!static::isIceBox()){
                $iceBoxName=null;
            } else {
                $path=rtrim(dirname(__DIR__,2),'/');
                if(!str_starts_with($path, '/var/www/icebear-')){
                    //Shouldn't happen.
                    $iceBoxName=null;
                } else {
                    $iceBoxName=str_replace('/var/www/icebear-','',$path);
                }
            }
        }
        if(session::exists()){
            session::set('iceBoxName', $iceBoxName);
        }
        return $iceBoxName;
    }

	/**
	 * @throws BadRequestException
	 * @throws ServerException
	 */
	public static function getDatabaseVersion(): string {
		return updater::getDatabaseVersion();
	}

	/**
	 * @throws ServerException
	 */
	public static function getCodeVersion(): string {
		return updater::getCodeVersion();
	}

}