import DatabaseProperty from "../Database/DatabaseProperty";
import Email from "../Email";
import BadDataException from "../Exception/BadDataException";
import { ObjectType } from "../JSON";
import Typeof from "../Typeof";
import Hostname from "./Hostname";
import Protocol from "./Protocol";
import Route from "./Route";
export default class URL extends DatabaseProperty {
    get route() {
        return this._route;
    }
    set route(v) {
        this._route = v;
    }
    get params() {
        return this._params;
    }
    set params(v) {
        this._params = v;
    }
    get email() {
        return this._email;
    }
    set email(v) {
        this._email = v;
    }
    get hostname() {
        return this._hostname;
    }
    set hostname(v) {
        this._hostname = v;
    }
    get protocol() {
        return this._protocol;
    }
    set protocol(v) {
        this._protocol = v;
    }
    constructor(protocol, hostname, route, queryString) {
        super();
        this._route = new Route();
        this._params = {};
        this._protocol = Protocol.HTTPS;
        if (typeof hostname === Typeof.String &&
            Email.isValid(hostname)) {
            this.email = new Email(hostname);
        }
        else if (hostname instanceof Email) {
            this.email = hostname;
        }
        else if (hostname instanceof Hostname) {
            this.hostname = hostname;
        }
        else if (typeof hostname === Typeof.String) {
            this.hostname = Hostname.fromString(hostname);
        }
        this.protocol = protocol;
        if (route) {
            this.route = route;
        }
        if (queryString) {
            const keyValues = queryString.split("&");
            for (const keyValue of keyValues) {
                if (keyValue.split("=")[0] && keyValue.split("=")[1]) {
                    const key = keyValue.split("=")[0];
                    const value = keyValue.split("=")[1];
                    if (key && value) {
                        this._params[key] = value;
                    }
                }
            }
        }
    }
    isHttps() {
        return this.protocol === Protocol.HTTPS;
    }
    toString() {
        let urlString = `${this.protocol}${this.hostname || this.email}`;
        if (!this.email && !urlString.startsWith("mailto:")) {
            if (this.route && this.route.toString().startsWith("/")) {
                if (urlString.endsWith("/")) {
                    urlString = urlString.substring(0, urlString.length - 1);
                }
                urlString += this.route.toString();
            }
            else {
                if (urlString.endsWith("/")) {
                    urlString = urlString.substring(0, urlString.length - 1);
                }
                urlString += "/" + this.route.toString();
            }
            if (Object.keys(this.params).length > 0) {
                urlString += "?";
                for (const key of Object.keys(this.params)) {
                    urlString += key + "=" + this.params[key] + "&";
                }
                urlString = urlString.substring(0, urlString.length - 1); // remove last &
            }
        }
        return urlString;
    }
    static fromURL(url) {
        return URL.fromString(url.toString());
    }
    static fromString(url) {
        let protocol = Protocol.HTTPS;
        if (url.startsWith("https://")) {
            protocol = Protocol.HTTPS;
            url = url.replace("https://", "");
        }
        if (url.startsWith("http://")) {
            protocol = Protocol.HTTP;
            url = url.replace("http://", "");
        }
        if (url.startsWith("wss://")) {
            protocol = Protocol.WSS;
            url = url.replace("wss://", "");
        }
        if (url.startsWith("ws://")) {
            protocol = Protocol.WS;
            url = url.replace("ws://", "");
        }
        if (url.startsWith("mongodb://")) {
            protocol = Protocol.MONGO_DB;
            url = url.replace("mongodb://", "");
        }
        if (url.startsWith("mailto:")) {
            protocol = Protocol.MAIL;
            url = url.replace("mailto:", "");
        }
        const hostname = new Hostname(url.split("/")[0] || "");
        let route;
        if (url.split("/").length > 1) {
            const paths = url.split("/");
            paths.shift();
            route = new Route(paths.join("/").split("?")[0]);
        }
        const queryString = url.split("?")[1] || "";
        return new URL(protocol, hostname, route, queryString);
    }
    removeQueryString() {
        return URL.fromString(this.toString().split("?")[0] || "");
    }
    toJSON() {
        return {
            _type: ObjectType.URL,
            value: this.toString(),
        };
    }
    static fromJSON(json) {
        if (json["_type"] === ObjectType.URL) {
            return URL.fromString(json["value"] || "");
        }
        throw new BadDataException("Invalid JSON: " + JSON.stringify(json));
    }
    addRoute(route) {
        if (typeof route === Typeof.String) {
            this.route.addRoute(new Route(route.toString()));
        }
        if (route instanceof Route) {
            this.route.addRoute(route);
        }
        return this;
    }
    addQueryParam(paramName, value, encode) {
        if (encode) {
            value = encodeURIComponent(value);
        }
        this.params[paramName] = value;
        return this;
    }
    getQueryParam(paramName) {
        return this.params[paramName] || null;
    }
    addQueryParams(params) {
        this.params = Object.assign(Object.assign({}, this.params), params);
        return this;
    }
    getLastRoute(getFromLastRoute) {
        const paths = this.route.toString().split("/");
        if (paths.length > 0) {
            if (!getFromLastRoute) {
                return new Route("/" + paths[paths.length - 1]);
            }
            return new Route("/" + paths[paths.length - (1 + getFromLastRoute)]);
        }
        return null;
    }
    static toDatabase(value) {
        if (value) {
            if (typeof value === "string") {
                value = URL.fromString(value);
            }
            return value.toString();
        }
        return null;
    }
    static fromDatabase(_value) {
        if (_value) {
            return URL.fromString(_value);
        }
        return null;
    }
}
//# sourceMappingURL=URL.js.map