/*
 * Copyright (C) 2021 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.libraries.entitlement.http;

import static com.android.libraries.entitlement.ServiceEntitlementException.ERROR_HTTP_STATUS_NOT_SUCCESS;
import static com.android.libraries.entitlement.ServiceEntitlementException.ERROR_MALFORMED_HTTP_RESPONSE;
import static com.android.libraries.entitlement.ServiceEntitlementException.ERROR_SERVER_NOT_CONNECTABLE;
import static com.android.libraries.entitlement.http.HttpConstants.RequestMethod.POST;
import static com.android.libraries.entitlement.utils.DebugUtils.logPii;

import static com.google.common.base.Strings.nullToEmpty;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.SECONDS;

import android.net.Network;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.WorkerThread;

import com.android.libraries.entitlement.ServiceEntitlementException;
import com.android.libraries.entitlement.http.HttpConstants.ContentType;
import com.android.libraries.entitlement.utils.StreamUtils;

import com.google.common.collect.ImmutableList;
import com.google.common.net.HttpHeaders;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

/** Implement the HTTP request method according to TS.43 specification. */
public class HttpClient {
    private static final String TAG = "ServiceEntitlement";

    private HttpURLConnection mConnection;

    @WorkerThread
    public HttpResponse request(HttpRequest request) throws ServiceEntitlementException {
        logPii("HttpClient.request url: " + request.url());
        createConnection(request);
        logPii("HttpClient.request headers (partial): " + mConnection.getRequestProperties());
        try {
            if (POST.equals(request.requestMethod())) {
                try (OutputStream out = new DataOutputStream(mConnection.getOutputStream())) {
                    // Android JSON toString() escapes forward-slash with back-slash. It's not
                    // supported by some vendor and not mandatory in JSON spec. Undo escaping.
                    String postData = request.postData().toString().replace("\\/", "/");
                    out.write(postData.getBytes(UTF_8));
                    logPii("HttpClient.request post data: " + postData);
                }
            }
            mConnection.connect(); // This is to trigger SocketTimeoutException early
            HttpResponse response = getHttpResponse(mConnection);
            Log.d(TAG, "HttpClient.response : " + response);
            return response;
        } catch (IOException ioe) {
            throw new ServiceEntitlementException(
                    ERROR_HTTP_STATUS_NOT_SUCCESS,
                    StreamUtils.inputStreamToStringSafe(mConnection.getErrorStream()),
                    ioe);
        } finally {
            closeConnection();
        }
    }

    private void createConnection(HttpRequest request) throws ServiceEntitlementException {
        try {
            URL url = new URL(request.url());
            Network network = request.network();
            if (network == null) {
                mConnection = (HttpURLConnection) url.openConnection();
            } else {
                mConnection = (HttpURLConnection) network.openConnection(url);
            }

            // add HTTP headers
            for (Map.Entry<String, String> entry : request.requestProperties().entries()) {
                mConnection.addRequestProperty(entry.getKey(), entry.getValue());
            }

            // set parameters
            mConnection.setRequestMethod(request.requestMethod());
            mConnection.setConnectTimeout((int) SECONDS.toMillis(request.timeoutInSec()));
            mConnection.setReadTimeout((int) SECONDS.toMillis(request.timeoutInSec()));
            if (POST.equals(request.requestMethod())) {
                mConnection.setDoOutput(true);
            }
        } catch (IOException ioe) {
            throw new ServiceEntitlementException(
                    ERROR_SERVER_NOT_CONNECTABLE, "Configure connection failed!", ioe);
        }
    }

    private void closeConnection() {
        if (mConnection != null) {
            mConnection.disconnect();
            mConnection = null;
        }
    }

    private static HttpResponse getHttpResponse(HttpURLConnection connection)
            throws ServiceEntitlementException {
        HttpResponse.Builder responseBuilder = HttpResponse.builder();
        responseBuilder.setContentType(getContentType(connection));
        try {
            int responseCode = connection.getResponseCode();
            logPii("HttpClient.response headers: " + connection.getHeaderFields());
            if (responseCode != HttpURLConnection.HTTP_OK) {
                throw new ServiceEntitlementException(ERROR_HTTP_STATUS_NOT_SUCCESS, responseCode,
                        connection.getHeaderField(HttpHeaders.RETRY_AFTER),
                        "Invalid connection response");
            }
            responseBuilder.setResponseCode(responseCode);
            responseBuilder.setResponseMessage(nullToEmpty(connection.getResponseMessage()));
        } catch (IOException e) {
            throw new ServiceEntitlementException(
                    ERROR_HTTP_STATUS_NOT_SUCCESS, "Read response code failed!", e);
        }
        responseBuilder.setCookies(getCookies(connection));
        try {
            String responseBody = readResponse(connection);
            logPii("HttpClient.response body: " + responseBody);
            responseBuilder.setBody(responseBody);
        } catch (IOException e) {
            throw new ServiceEntitlementException(
                    ERROR_MALFORMED_HTTP_RESPONSE, "Read response body/message failed!", e);
        }
        return responseBuilder.build();
    }

    private static String readResponse(URLConnection connection) throws IOException {
        try (InputStream in = connection.getInputStream()) {
            return StreamUtils.inputStreamToStringSafe(in);
        }
    }

    private static int getContentType(URLConnection connection) {
        String contentType = connection.getHeaderField(ContentType.NAME);
        if (TextUtils.isEmpty(contentType)) {
            return ContentType.UNKNOWN;
        }

        if (contentType.contains("xml")) {
            return ContentType.XML;
        } else if ("text/vnd.wap.connectivity".equals(contentType)) {
            // Workaround that a server vendor uses this type for XML
            return ContentType.XML;
        } else if (contentType.contains("json")) {
            return ContentType.JSON;
        }
        return ContentType.UNKNOWN;
    }

    private static List<String> getCookies(URLConnection connection) {
        List<String> cookies = connection.getHeaderFields().get(HttpHeaders.SET_COOKIE);
        return cookies == null ? ImmutableList.of() : cookies;
    }
}
