/*
 * Copyright (C) 2010 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.browser;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import libcore.io.Streams;
import libcore.net.http.ResponseUtils;

public class GoogleAccountLogin implements Runnable,
        AccountManagerCallback<Bundle>, OnCancelListener {

    private static final String LOGTAG = "BrowserLogin";

    // Url for issuing the uber token.
    private Uri ISSUE_AUTH_TOKEN_URL = Uri.parse(
            "https://www.google.com/accounts/IssueAuthToken?service=gaia&Session=false");
    // Url for signing into a particular service.
    private static final Uri TOKEN_AUTH_URL = Uri.parse(
            "https://www.google.com/accounts/TokenAuth");
    // Google account type
    private static final String GOOGLE = "com.google";
    // Last auto login time
    public static final String PREF_AUTOLOGIN_TIME = "last_autologin_time";

    private final Activity mActivity;
    private final Account mAccount;
    private final WebView mWebView;
    private Runnable mRunnable;
    private ProgressDialog mProgressDialog;

    // SID and LSID retrieval process.
    private String mSid;
    private String mLsid;
    private int mState;  // {NONE(0), SID(1), LSID(2)}
    private boolean mTokensInvalidated;
    private String mUserAgent;

    private GoogleAccountLogin(Activity activity, Account account,
            Runnable runnable) {
        mActivity = activity;
        mAccount = account;
        mWebView = new WebView(mActivity);
        mRunnable = runnable;
        mUserAgent = mWebView.getSettings().getUserAgentString();

        // XXX: Doing pre-login causes onResume to skip calling
        // resumeWebViewTimers. So to avoid problems with timers not running, we
        // duplicate the work here using the off-screen WebView.
        CookieSyncManager.getInstance().startSync();
        WebViewTimersControl.getInstance().onBrowserActivityResume(mWebView);

        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return false;
            }
            @Override
            public void onPageFinished(WebView view, String url) {
                done();
            }
        });
    }

    private void saveLoginTime() {
        Editor ed = BrowserSettings.getInstance().getPreferences().edit();
        ed.putLong(PREF_AUTOLOGIN_TIME, System.currentTimeMillis());
        ed.apply();
    }

    // Runnable
    @Override
    public void run() {
        String urlString = ISSUE_AUTH_TOKEN_URL.buildUpon()
                .appendQueryParameter("SID", mSid)
                .appendQueryParameter("LSID", mLsid)
                .build().toString();

        HttpURLConnection connection = null;
        String authToken = null;
        try {
            URL url = new URL(urlString);
            // Intentionally not using Proxy.
            connection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("User-Agent", mUserAgent);

            int status = connection.getResponseCode();
            if (status != HttpURLConnection.HTTP_OK) {
                Log.d(LOGTAG, "LOGIN_FAIL: Bad status from auth url "
                      + status + ": " + connection.getResponseMessage());
                // Invalidate the tokens once just in case the 403 was for other
                // reasons.
                if (status == HttpURLConnection.HTTP_FORBIDDEN && !mTokensInvalidated) {
                    Log.d(LOGTAG, "LOGIN_FAIL: Invalidating tokens...");
                    // Need to regenerate the auth tokens and try again.
                    invalidateTokens();
                    // XXX: Do not touch any more member variables from this
                    // thread as a second thread will handle the next login
                    // attempt.
                    return;
                }
                done();
                return;
            }

            final Charset responseCharset = ResponseUtils.responseCharset(
                    connection.getContentType());
            byte[] responseBytes = Streams.readFully(connection.getInputStream());
            authToken = new String(responseBytes, responseCharset);
        } catch (Exception e) {
            Log.d(LOGTAG, "LOGIN_FAIL: Exception acquiring uber token " + e);
            done();
            return;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }

        final String newUrl = TOKEN_AUTH_URL.buildUpon()
                .appendQueryParameter("source", "android-browser")
                .appendQueryParameter("auth", authToken)
                .appendQueryParameter("continue",
                        BrowserSettings.getFactoryResetHomeUrl(mActivity))
                .build().toString();
        mActivity.runOnUiThread(new Runnable() {
            @Override public void run() {
                // Check mRunnable in case the request has been canceled.  This
                // is most likely not necessary as run() is the only non-UI
                // thread that calls done() but I am paranoid.
                synchronized (GoogleAccountLogin.this) {
                    if (mRunnable == null) {
                        return;
                    }
                    mWebView.loadUrl(newUrl);
                }
            }
        });
    }

    private void invalidateTokens() {
        AccountManager am = AccountManager.get(mActivity);
        am.invalidateAuthToken(GOOGLE, mSid);
        am.invalidateAuthToken(GOOGLE, mLsid);
        mTokensInvalidated = true;
        mState = 1;  // SID
        am.getAuthToken(mAccount, "SID", null, mActivity, this, null);
    }

    // AccountManager callbacks.
    @Override
    public void run(AccountManagerFuture<Bundle> value) {
        try {
            String id = value.getResult().getString(
                    AccountManager.KEY_AUTHTOKEN);
            switch (mState) {
                default:
                case 0:
                    throw new IllegalStateException(
                            "Impossible to get into this state");
                case 1:
                    mSid = id;
                    mState = 2;  // LSID
                    AccountManager.get(mActivity).getAuthToken(
                            mAccount, "LSID", null, mActivity, this, null);
                    break;
                case 2:
                    mLsid = id;
                    new Thread(this).start();
                    break;
            }
        } catch (Exception e) {
            Log.d(LOGTAG, "LOGIN_FAIL: Exception in state " + mState + " " + e);
            // For all exceptions load the original signin page.
            // TODO: toast login failed?
            done();
        }
    }

    // Start the login process if auto-login is enabled and the user is not
    // already logged in.
    public static void startLoginIfNeeded(Activity activity,
            Runnable runnable) {
        // Already logged in?
        if (isLoggedIn()) {
            runnable.run();
            return;
        }

        // No account found?
        Account[] accounts = getAccounts(activity);
        if (accounts == null || accounts.length == 0) {
            runnable.run();
            return;
        }

        GoogleAccountLogin login =
                new GoogleAccountLogin(activity, accounts[0], runnable);
        login.startLogin();
    }

    private void startLogin() {
        saveLoginTime();
        mProgressDialog = ProgressDialog.show(mActivity,
                mActivity.getString(R.string.pref_autologin_title),
                mActivity.getString(R.string.pref_autologin_progress,
                                    mAccount.name),
                true /* indeterminate */,
                true /* cancelable */,
                this);
        mState = 1;  // SID
        AccountManager.get(mActivity).getAuthToken(
                mAccount, "SID", null, mActivity, this, null);
    }

    private static Account[] getAccounts(Context ctx) {
        return AccountManager.get(ctx).getAccountsByType(GOOGLE);
    }

    // Checks if we already did pre-login.
    private static boolean isLoggedIn() {
        // See if we last logged in less than a week ago.
        long lastLogin = BrowserSettings.getInstance().getPreferences()
                .getLong(PREF_AUTOLOGIN_TIME, -1);
        if (lastLogin == -1) {
            return false;
        }
        return true;
    }

    // Used to indicate that the Browser should continue loading the main page.
    // This can happen on success, error, or timeout.
    private synchronized void done() {
        if (mRunnable != null) {
            Log.d(LOGTAG, "Finished login attempt for " + mAccount.name);
            mActivity.runOnUiThread(mRunnable);

            try {
                mProgressDialog.dismiss();
            } catch (Exception e) {
                // TODO: Switch to a managed dialog solution (DialogFragment?)
                // Also refactor this class, it doesn't
                // play nice with the activity lifecycle, leading to issues
                // with the dialog it manages
                Log.w(LOGTAG, "Failed to dismiss mProgressDialog: " + e.getMessage());
            }
            mRunnable = null;
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mWebView.destroy();
                }
            });
        }
    }

    // Called by the progress dialog on startup.
    public void onCancel(DialogInterface unused) {
        done();
    }

}
