/*
 * 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.testing;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;
import javax.net.ssl.HttpsURLConnection;

/**
 * A {@link URLStreamHandlerFactory} to return faked {@link URLConnection}, as {@link URL} is a
 * final class and {@link URL#openConnection} cannot be mocked using mockito.
 */
public class FakeURLStreamHandler extends URLStreamHandler implements URLStreamHandlerFactory {
    private Map<String, FakeResponse> mResponses = ImmutableMap.of();
    private List<FakeHttpsURLConnection> mConnections = new ArrayList<>();

    private static final String ACCESS_TOKEN = "8dGozfI6%2FEaSsE7LaTfJKwdy";
    private static final String LOCATION = "Location";
    private static final String CONTENT_TYPE = "Content-Type";
    private static final String RETRY_AFTER = "Retry-After";

    @Override
    public URLConnection openConnection(URL u) {
        FakeHttpsURLConnection connection =
                new FakeHttpsURLConnection(u, mResponses.get(u.toString()));
        mConnections.add(connection);
        return connection;
    }

    @Override
    public URLStreamHandler createURLStreamHandler(String protocol) {
        return this;
    }

    /**
     * Prepares canned responses. Must be called before using this handler to open any {@link
     * URLConnection}.
     */
    public FakeURLStreamHandler stubResponse(Map<String, FakeResponse> response) {
        mResponses = response;
        mConnections = new ArrayList<>();
        return this;
    }

    /** Returns {@link URLConnection}s opened by this handler since last {@link #stubResponse}. */
    public ImmutableList<FakeHttpsURLConnection> getConnections() {
        return ImmutableList.copyOf(mConnections);
    }

    /** Faked {@link HttpsURLConnection} to avoid making any network connection. */
    public static class FakeHttpsURLConnection extends HttpsURLConnection {
        private final FakeResponse mResponse;
        private final ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();

        public FakeHttpsURLConnection(URL url, FakeResponse response) {
            super(url);
            mResponse = response;
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(mResponse.responseBody());
        }

        @Override
        public OutputStream getOutputStream() {
            return mOutputStream;
        }

        public byte[] getBytesWrittenToOutputStream() {
            return mOutputStream.toByteArray();
        }

        @Override
        public int getResponseCode() {
            return mResponse.responseCode();
        }

        @Override
        public Map<String, List<String>> getHeaderFields() {
            List<String> locationList = ImmutableList.of("access_token=" + ACCESS_TOKEN);
            return ImmutableMap.of("Location", locationList);
        }

        @Override
        public String getHeaderField(String name) {
            switch (name) {
                case LOCATION:
                    return "Location: " + mResponse.responseLocation();
                case CONTENT_TYPE:
                    return mResponse.contentType();
                case RETRY_AFTER:
                    return mResponse.retryAfter();
                default:
                    return null;
            }
        }

        @Override
        public void connect() {
        }

        @Override
        public void disconnect() {
        }

        @Override
        public boolean usingProxy() {
            return false;
        }

        @Override
        public String getCipherSuite() {
            return null;
        }

        @Override
        public Certificate[] getLocalCertificates() {
            return null;
        }

        @Override
        public Certificate[] getServerCertificates() {
            return null;
        }
    }

    @AutoValue
    public abstract static class FakeResponse {
        public abstract int responseCode();

        @Nullable
        public abstract String responseLocation();

        @SuppressWarnings("mutable") // For test only
        public abstract byte[] responseBody();

        public abstract String contentType();

        public abstract String retryAfter();

        public static Builder builder() {
            return new AutoValue_FakeURLStreamHandler_FakeResponse.Builder()
                    .setResponseBody(new byte[]{})
                    .setContentType("")
                    .setResponseCode(0)
                    .setResponseLocation("")
                    .setRetryAfter("");
        }

        @AutoValue.Builder
        public abstract static class Builder {
            public abstract Builder setResponseCode(int value);

            public abstract Builder setResponseLocation(String value);

            public abstract Builder setResponseBody(byte[] value);

            public abstract Builder setContentType(String contentType);

            public abstract Builder setRetryAfter(String retryAfter);

            public abstract FakeResponse build();
        }
    }
}
