/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.statementservice.retriever;

import org.json.JSONObject;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;

/**
 * Immutable value type that names a web asset.
 *
 * <p>A web asset can be named by its protocol, domain, and port using this JSON string:
 *     { "namespace": "web",
 *       "site": "[protocol]://[fully-qualified domain]{:[optional port]}" }
 *
 * <p>For example, a website hosted on a https server at www.test.com can be named using
 *     { "namespace": "web",
 *       "site": "https://www.test.com" }
 *
 * <p>The only protocol supported now are https and http. If the optional port is not specified,
 * the default for each protocol will be used (i.e. 80 for http and 443 for https).
 */
/* package private */ final class WebAsset extends AbstractAsset {

    private static final String MISSING_FIELD_FORMAT_STRING = "Expected %s to be set.";
    private static final String SCHEME_HTTP = "http";

    private final URL mUrl;

    private WebAsset(URL url) {
        int port = url.getPort() != -1 ? url.getPort() : url.getDefaultPort();
        try {
            mUrl = new URL(url.getProtocol().toLowerCase(), url.getHost().toLowerCase(), port, "");
        } catch (MalformedURLException e) {
            throw new AssertionError(
                    "Url should always be validated before calling the constructor.");
        }
    }

    public String getDomain() {
        return mUrl.getHost();
    }

    public String getPath() {
        return mUrl.getPath();
    }

    public String getScheme() {
        return mUrl.getProtocol();
    }

    public int getPort() {
        return mUrl.getPort();
    }

    @Override
    public String toJson() {
        AssetJsonWriter writer = new AssetJsonWriter();

        writer.writeFieldLower(Utils.NAMESPACE_FIELD, Utils.NAMESPACE_WEB);
        writer.writeFieldLower(Utils.WEB_ASSET_FIELD_SITE, mUrl.toExternalForm());

        return writer.closeAndGetString();
    }

    @Override
    public String toString() {
        StringBuilder asset = new StringBuilder();
        asset.append("WebAsset: ");
        asset.append(toJson());
        return asset.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof WebAsset)) {
            return false;
        }

        return ((WebAsset) o).toJson().equals(toJson());
    }

    @Override
    public int hashCode() {
        return toJson().hashCode();
    }

    @Override
    public int lookupKey() {
        return toJson().hashCode();
    }

    @Override
    public boolean followInsecureInclude() {
        // Only allow insecure include file if the asset scheme is http.
        return SCHEME_HTTP.equals(getScheme());
    }

    /**
     * Checks that the input is a valid web asset.
     *
     * @throws AssociationServiceException if the asset is not well formatted.
     */
    protected static WebAsset create(JSONObject asset)
            throws AssociationServiceException {
        if (asset.optString(Utils.WEB_ASSET_FIELD_SITE).equals("")) {
            throw new AssociationServiceException(String.format(MISSING_FIELD_FORMAT_STRING,
                    Utils.WEB_ASSET_FIELD_SITE));
        }

        URL url;
        try {
            url = new URL(asset.optString(Utils.WEB_ASSET_FIELD_SITE));
        } catch (MalformedURLException e) {
            throw new AssociationServiceException("Url is not well formatted.", e);
        }

        String scheme = url.getProtocol().toLowerCase(Locale.US);
        if (!scheme.equals("https") && !scheme.equals("http")) {
            throw new AssociationServiceException("Expected scheme to be http or https.");
        }

        if (url.getUserInfo() != null) {
            throw new AssociationServiceException("The url should not contain user info.");
        }

        String path = url.getFile(); // This is url.getPath() + url.getQuery().
        if (!path.equals("/") && !path.equals("")) {
            throw new AssociationServiceException(
                    "Site should only have scheme, domain, and port.");
        }

        return new WebAsset(url);
    }
}
