<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */
declare (strict_types=1);
namespace Packetery\Nette\Http;

use Packetery\Nette;
/**
 * Immutable representation of a URL with application base-path.
 *
 * <pre>
 *      baseUrl    basePath  relativePath  relativeUrl
 *         |          |        |               |
 * /---------------/-----\/--------\-----------------------------\
 * http://nette.org/admin/script.php/pathinfo/?name=param#fragment
 *                 \_______________/\________/
 *                        |              |
 *                   scriptPath       pathInfo
 * </pre>
 *
 * @property-read string $scriptPath
 * @property-read string $basePath
 * @property-read string $relativePath
 * @property-read string $baseUrl
 * @property-read string $relativeUrl
 * @property-read string $pathInfo
 */
class UrlScript extends UrlImmutable
{
    /** @var string */
    private $scriptPath;
    /** @var string */
    private $basePath;
    public function __construct($url = '/', string $scriptPath = '')
    {
        parent::__construct($url);
        $this->scriptPath = $scriptPath;
        $this->build();
    }
    /** @return static */
    public function withPath(string $path, string $scriptPath = '')
    {
        $dolly = clone $this;
        $dolly->scriptPath = $scriptPath;
        $parent = \Closure::fromCallable([UrlImmutable::class, 'withPath'])->bindTo($dolly);
        return $parent($path);
    }
    public function getScriptPath() : string
    {
        return $this->scriptPath;
    }
    public function getBasePath() : string
    {
        return $this->basePath;
    }
    public function getRelativePath() : string
    {
        return \substr($this->getPath(), \strlen($this->basePath));
    }
    public function getBaseUrl() : string
    {
        return $this->getHostUrl() . $this->basePath;
    }
    public function getRelativeUrl() : string
    {
        return \substr($this->getAbsoluteUrl(), \strlen($this->getBaseUrl()));
    }
    /**
     * Returns the additional path information.
     */
    public function getPathInfo() : string
    {
        return (string) \substr($this->getPath(), \strlen($this->scriptPath));
    }
    protected function build() : void
    {
        parent::build();
        $path = $this->getPath();
        $this->scriptPath = $this->scriptPath ?: $path;
        $pos = \strrpos($this->scriptPath, '/');
        if ($pos === \false || \strncmp($this->scriptPath, $path, $pos + 1)) {
            throw new \Packetery\Nette\InvalidArgumentException("ScriptPath '{$this->scriptPath}' doesn't match path '{$path}'");
        }
        $this->basePath = \substr($this->scriptPath, 0, $pos + 1);
    }
}
