package mil.nga.mapcache.io.network;

import android.app.Activity;
import android.util.Base64;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import mil.nga.mapcache.auth.Authenticator;
import mil.nga.mapcache.auth.UserLoggerInner;
import mil.nga.mapcache.utils.HttpUtils;

/**
 * An http get request class that performs any specified http get.
 */
public class HttpGetRequest implements Runnable, Authenticator {

    /**
     * The url of the get request.
     */
    private String urlString;

    /**
     * Object that is called when request is completed.
     */
    private IResponseHandler handler;

    /**
     * Used to get the app name and version for the user agent.
     */
    private Activity activity;

    /**
     * Retrieves the user's username and password then calls back for authentication.
     */
    private UserLoggerInner loggerInner = null;

    /**
     * The http connection.
     */
    private HttpURLConnection connection = null;

    /**
     * The authorization string from previous Http request.
     */
    private String authorization = null;

    /**
     * Constructs a new HttpGetRequest.
     *
     * @param url      The url of the get request.
     * @param handler  Object this is called when request is completed.
     * @param activity Used to get the app name and version for the user agent.
     */
    public HttpGetRequest(String url, IResponseHandler handler, Activity activity) {
        this.urlString = url;
        this.handler = handler;
        this.activity = activity;
    }

    @Override
    public void run() {
        try {
            authorization = null;
            URL url = new URL(urlString);
            connection = (HttpURLConnection) url.openConnection();
            configureRequest(connection);
            connection.connect();

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
                addBasicAuth(connection);
                responseCode = connection.getResponseCode();
            }

            if (responseCode == HttpURLConnection.HTTP_MOVED_PERM
                    || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
                    || responseCode == HttpURLConnection.HTTP_SEE_OTHER) {
                String redirect = connection.getHeaderField("Location");
                connection.disconnect();
                url = new URL(redirect);
                connection = (HttpURLConnection) url.openConnection();
                configureRequest(connection);
                connection.connect();
            }

            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                this.handler.handleResponse(null, responseCode);
            } else {
                InputStream stream = connection.getInputStream();
                this.handler.handleResponse(stream, responseCode);
                if (this.handler instanceof AuthorizationConsumer) {
                    ((AuthorizationConsumer) this.handler).setAuthorizationValue(this.authorization);
                }
            }

        } catch (IOException e) {
            this.handler.handleException(e);
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    /**
     * Adds basic auth to the connection.
     *
     * @param connection The connection to add basic auth to.
     */
    private void addBasicAuth(HttpURLConnection connection) {
        if (loggerInner == null) {
            loggerInner = new UserLoggerInner(activity);
        }
        loggerInner.login(connection.getURL(), this);
    }

    /**
     * Adds the user agent to the http header.
     *
     * @param connection The connection to add the user agent to.
     */
    private void configureRequest(HttpURLConnection connection) {
        connection.addRequestProperty(
                HttpUtils.getInstance().getUserAgentKey(),
                HttpUtils.getInstance().getUserAgentValue(activity));
    }

    @Override
    public boolean authenticate(URL url, String userName, String password) {
        boolean authorized = false;

        try {
            if (connection != null) {
                connection.disconnect();
            }

            connection = (HttpURLConnection) url.openConnection();
            configureRequest(connection);

            String usernamePass = userName + ":" + password;
            authorization = "Basic " + Base64.encodeToString(usernamePass.getBytes(), Base64.NO_WRAP);
            connection.addRequestProperty(HttpUtils.getInstance().getBasicAuthKey(), authorization);
            connection.connect();
            authorized = connection.getResponseCode() != HttpURLConnection.HTTP_UNAUTHORIZED;
        } catch (IOException e) {
            Log.e(HttpGetRequest.class.getSimpleName(), e.getMessage(), e);
        }

        return authorized;
    }
}

@@ -225,16 +225,61 @@
 net.URL;
+%0Aimport java.util.List;%0Aimport java.util.Map;
 %0A%0Aimport
@@ -4158,16 +4158,886 @@
 ivity));
+%0A%0A        // Used for debugging connection issues%0A        connection.addRequestProperty(%22Accept%22, %22text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9%22);%0A        connection.addRequestProperty(%22Accept-Language%22, %22en-US,en;q=0.9%22);%0A        connection.addRequestProperty(%22Cache-Control%22, %22no-cache%22);%0A        connection.addRequestProperty(%22Connection%22, %22keep-alive%22);%0A        connection.addRequestProperty(%22Host%22, connection.getURL().getAuthority());%0A        connection.addRequestProperty(%22Sec-Fetch-Dest%22, %22document%22);%0A        connection.addRequestProperty(%22Sec-Fetch-Mode%22, %22navigate%22);%0A        connection.addRequestProperty(%22Sec-Fetch-Site%22, %22none%22);%0A        connection.addRequestProperty(%22Sec-Fetch-User%22, %22?1%22);%0A        connection.addRequestProperty(%22Upgrade-Insecure-Requests%22, %221%22);
 %0A    %7D%0A%0A
@@ -5775,16 +5775,295 @@
 ORIZED;%0A
+            if(!authorized) %7B%0A                for (Map.Entry%3CString, List%3CString%3E%3E entries : connection.getHeaderFields().entrySet()) %7B%0A                    Log.e(HttpGetRequest.class.getSimpleName(), entries.getKey() + %22: %22 + entries.getValue());%0A                %7D%0A            %7D%0A
         

add some debugging code