public function toString(bool $idn = false)
    {
        $o = "";
        if (!empty($this->scheme))
            $o .= $this->scheme . "://";
        
        if (!empty($this->username) && !empty($this->password))
            $o .= $this->username . ':' . $this->password . '@';

        // Check for IDN
        $host = $this->host;
        if ($idn && preg_match('/[^\x20-\x7f]/', $host))
            $host = \idn_to_ascii($host);
        $o .= $host;

        if (!empty($this->port))
        {
            if (!(
                ($this->scheme === "http"  && $this->port === 80) ||
                ($this->scheme === "https" && $this->port === 443) || 
                ($this->scheme === "ftp"   && $this->port === 21)
            ))
                $o .= ":" . $this->port;
        }

        $o .= $this->path;
        $query = $this->getQuery();

        if (!empty($query))
            $o .= '?' . $query;

        if (!empty($this->fragment))
            $o .= '#' . $this->fragment;

        return $o;
    }