/*
 * Copyright (C) 2006 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 android.webkit;

import android.content.Context;
import android.net.http.*;
import android.os.*;
import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Map;

import junit.framework.Assert;

class Network {

    private static final String LOGTAG = "network";

    /**
     * Static instance of a Network object.
     */
    private static Network sNetwork;
    
    /**
     * Flag to store the state of platform notifications, for the case
     * when the Network object has not been constructed yet
     */
    private static boolean sPlatformNotifications;
    
    /**
     * Reference count for platform notifications as the network class is a 
     * static and can exist over multiple activities, thus over multiple 
     * onPause/onResume pairs. 
     */
    private static int sPlatformNotificationEnableRefCount;

    /**
     * Proxy username if known (used for pre-emptive proxy authentication).
     */
    private String mProxyUsername;

    /**
     * Proxy password if known (used for pre-emptive proxy authentication).
     */
    private String mProxyPassword;

    /**
     * Network request queue (requests are added from the browser thread).
     */
    private RequestQueue mRequestQueue;

    /**
     * SSL error handler: takes care of synchronization of multiple async
     * loaders with SSL-related problems.
     */
    private SslErrorHandler mSslErrorHandler;

    /**
     * HTTP authentication handler: takes care of synchronization of HTTP
     * authentication requests.
     */
    private HttpAuthHandler mHttpAuthHandler;

    /**
     * @return The singleton instance of the network.
     */
    public static synchronized Network getInstance(Context context) {
        if (sNetwork == null) {
            // Note Context of the Application is used here, rather than
            // the what is passed in (usually a Context derived from an 
            // Activity) so the intent receivers belong to the application
            // rather than an activity - this fixes the issue where 
            // Activities are created and destroyed during the lifetime of
            // an Application
            sNetwork = new Network(context.getApplicationContext());
            if (sPlatformNotifications) {
                // Adjust the ref count before calling enable as it is already
                // taken into account when the static function was called 
                // directly
                --sPlatformNotificationEnableRefCount;
                enablePlatformNotifications();
            }
        }
        return sNetwork;
    }


    /**
     * Enables data state and proxy tracking
     */
    public static void enablePlatformNotifications() {
        if (++sPlatformNotificationEnableRefCount == 1) {
            if (sNetwork != null) {
                sNetwork.mRequestQueue.enablePlatformNotifications();
            } else {
                sPlatformNotifications = true;
            }
        }
    }

    /**
     * If platform notifications are enabled, this should be called
     * from onPause() or onStop()
     */
    public static void disablePlatformNotifications() {
        if (--sPlatformNotificationEnableRefCount == 0) {
            if (sNetwork != null) {
                sNetwork.mRequestQueue.disablePlatformNotifications();
            } else {
                sPlatformNotifications = false;
            }
        }
    }

    /**
     * Creates a new Network object.
     * XXX: Must be created in the same thread as WebCore!!!!!
     */
    private Network(Context context) {
        if (DebugFlags.NETWORK) {
            Assert.assertTrue(Thread.currentThread().
                    getName().equals(WebViewCore.THREAD_NAME));
        }
        mSslErrorHandler = new SslErrorHandler();
        mHttpAuthHandler = new HttpAuthHandler(this);

        mRequestQueue = new RequestQueue(context);
    }

    /**
     * Request a url from either the network or the file system.
     * @param url The url to load.
     * @param method The http method.
     * @param headers The http headers.
     * @param postData The body of the request.
     * @param loader A LoadListener for receiving the results of the request.
     * @return True if the request was successfully queued.
     */
    public boolean requestURL(String method,
                              Map<String, String> headers,
                              byte [] postData,
                              LoadListener loader) {

        String url = loader.url();

        // Not a valid url, return false because we won't service the request!
        if (!URLUtil.isValidUrl(url)) {
            return false;
        }

        // asset, res, file system or data stream are handled in the other code
        // path. This only handles network request.
        if (URLUtil.isAssetUrl(url) || URLUtil.isResourceUrl(url)
                || URLUtil.isFileUrl(url) || URLUtil.isDataUrl(url)) {
            return false;
        }

        /* FIXME: this is lame.  Pass an InputStream in, rather than
           making this lame one here */
        InputStream bodyProvider = null;
        int bodyLength = 0;
        if (postData != null) {
            bodyLength = postData.length;
            bodyProvider = new ByteArrayInputStream(postData);
        }

        RequestQueue q = mRequestQueue;
        RequestHandle handle = null;
        if (loader.isSynchronous()) {
            handle = q.queueSynchronousRequest(url, loader.getWebAddress(),
                    method, headers, loader, bodyProvider, bodyLength);
            loader.attachRequestHandle(handle);
            handle.processRequest();
            loader.loadSynchronousMessages();
        } else {
            handle = q.queueRequest(url, loader.getWebAddress(), method,
                    headers, loader, bodyProvider, bodyLength);
            // FIXME: Although this is probably a rare condition, normal network
            // requests are processed in a separate thread. This means that it
            // is possible to process part of the request before setting the
            // request handle on the loader. We should probably refactor this to
            // ensure the handle is attached before processing begins.
            loader.attachRequestHandle(handle);
        }

        return true;
    }

    /**
     * @return True iff there is a valid proxy set.
     */
    public boolean isValidProxySet() {
        // The proxy host and port can be set within a different thread during
        // an Intent broadcast.
        synchronized (mRequestQueue) {
            return mRequestQueue.getProxyHost() != null;
        }
    }

    /**
     * Get the proxy hostname.
     * @return The proxy hostname obtained from the network queue and proxy
     *         settings.
     */
    public String getProxyHostname() {
        return mRequestQueue.getProxyHost().getHostName();
    }

    /**
     * @return The proxy username or null if none.
     */
    public synchronized String getProxyUsername() {
        return mProxyUsername;
    }

    /**
     * Sets the proxy username.
     * @param proxyUsername Username to use when
     * connecting through the proxy.
     */
    public synchronized void setProxyUsername(String proxyUsername) {
        if (DebugFlags.NETWORK) {
            Assert.assertTrue(isValidProxySet());
        }

        mProxyUsername = proxyUsername;
    }

    /**
     * @return The proxy password or null if none.
     */
    public synchronized String getProxyPassword() {
        return mProxyPassword;
    }

    /**
     * Sets the proxy password.
     * @param proxyPassword Password to use when
     * connecting through the proxy.
     */
    public synchronized void setProxyPassword(String proxyPassword) {
        if (DebugFlags.NETWORK) {
            Assert.assertTrue(isValidProxySet());
        }

        mProxyPassword = proxyPassword;
    }

    /**
     * Saves the state of network handlers (user SSL and HTTP-authentication
     * preferences).
     * @param outState The out-state to save (write) to.
     * @return True iff succeeds.
     */
    public boolean saveState(Bundle outState) {
        if (DebugFlags.NETWORK) {
            Log.v(LOGTAG, "Network.saveState()");
        }

        return mSslErrorHandler.saveState(outState);
    }

    /**
     * Restores the state of network handlers (user SSL and HTTP-authentication
     * preferences).
     * @param inState The in-state to load (read) from.
     * @return True iff succeeds.
     */
    public boolean restoreState(Bundle inState) {
        if (DebugFlags.NETWORK) {
            Log.v(LOGTAG, "Network.restoreState()");
        }

        return mSslErrorHandler.restoreState(inState);
    }

    /**
     * Clears user SSL-error preference table.
     */
    public void clearUserSslPrefTable() {
        mSslErrorHandler.clear();
    }

    /**
     * Handles SSL error(s) on the way up to the user: the user must decide
     * whether errors should be ignored or not.
     * @param loader The loader that resulted in SSL errors.
     */
    public void handleSslErrorRequest(LoadListener loader) {
        if (DebugFlags.NETWORK) Assert.assertNotNull(loader);
        if (loader != null) {
            mSslErrorHandler.handleSslErrorRequest(loader);
        }
    }

    /* package */ boolean checkSslPrefTable(LoadListener loader,
            SslError error) {
        if (loader != null && error != null) {
            return mSslErrorHandler.checkSslPrefTable(loader, error);
        }
        return false;
    }

     /**
     * Handles authentication requests on their way up to the user (the user
     * must provide credentials).
     * @param loader The loader that resulted in an HTTP
     * authentication request.
     */
    public void handleAuthRequest(LoadListener loader) {
        if (DebugFlags.NETWORK) Assert.assertNotNull(loader);
        if (loader != null) {
            mHttpAuthHandler.handleAuthRequest(loader);
        }
    }

    // Performance probe
    public void startTiming() {
        mRequestQueue.startTiming();
    }

    public void stopTiming() {
        mRequestQueue.stopTiming();
    }
}
