package ru.yandex.wmtools.common;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * List of supported protocols in Webmaster Console.
 *
 * @author ailyin
 */
public enum SupportedProtocols implements Constants {
    HTTP("http", 80),
    HTTPS("https", 443);

    private final String scheme;
    private final int defaultPort;

    private SupportedProtocols(String scheme, int defaultPort) {
        this.scheme = scheme;
        this.defaultPort = defaultPort;
    }

    public String getScheme() {
        return scheme;
    }

    public int getDefaultPort() {
        return defaultPort;
    }

    /**
     * Returns project canonical hostname representation. Canonical hostname may contain protocol, hostname and port.
     * Following rules are used:
     * 1) hostname is always present
     * 2) protocol is omitted if it is 'http'
     * 3) port is omitted if it is default port for a given protocol
     *
     * @param url url
     * @return canonical hostname
     */
    public static String getCanonicalHostname(URL url) {
        for (SupportedProtocols protocol : values()) {
            if (protocol.scheme.equalsIgnoreCase(url.getProtocol())) {
                String result = (url.getPort() == protocol.defaultPort) ? url.getHost() : url.getAuthority();
                if (!HTTP.equals(protocol)) {
                    result = protocol.scheme + SCHEME_DELIMITER + result;
                }
                return result;
            }
        }

        throw new IllegalArgumentException("protocol isn't supported");
    }

    /**
     * Creates java.net.URL object for a given string representation of the url. Checks whether specified protocol is supported or not.
     * If no protocol is specified, it is assumed that it is HTTP.
     *
     * @param url string representation of the url
     * @return URL object
     * @throws MalformedURLException if given string is not a valid URL
     * @throws URISyntaxException if given string is not a valid URI
     * @throws UnsupportedProtocolException if specified protocol is not supported
     */
    public static URL getURL(String url) throws MalformedURLException, URISyntaxException, UnsupportedProtocolException {
        // check if one of the supported protocols is specified
        for (SupportedProtocols protocol : values()) {
            if (url.toLowerCase().startsWith(protocol.scheme + SCHEME_DELIMITER)) {
//                URI uri = new URI(protocol.scheme, url.substring(protocol.scheme.length() + 1), null);
                return new URL(/*uri.toASCIIString()*/protocol.scheme + url.substring(protocol.scheme.length()));
            }
        }

        // check if any protocol is specified
        if (url.contains(SCHEME_DELIMITER)) {
            if (url.indexOf("/") >= url.indexOf(SCHEME_DELIMITER)) {
                throw new UnsupportedProtocolException(url.substring(0, url.indexOf(SCHEME_DELIMITER)));
            }
        }

        // protocol is not specified => using default one (http)
//        URI uri = new URI(HTTP.scheme, "//" + url, null);
        return new URL(/*uri.toASCIIString()*/HTTP.scheme + SCHEME_DELIMITER + url);
    }

    public static class UnsupportedProtocolException extends Exception {
        private final String protocol;

        public UnsupportedProtocolException(String protocol) {
            this.protocol = protocol;
        }

        public String getProtocol() {
            return protocol;
        }
    }
}
