/*
 * Copyright (C) 2008 Esmertec AG.
 * Copyright (C) 2008 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.im.app;

import com.android.im.IChatSession;
import com.android.im.IChatSessionManager;
import com.android.im.IConnectionListener;
import com.android.im.IImConnection;
import com.android.im.R;
import com.android.im.app.adapter.ConnectionListenerAdapter;
import com.android.im.engine.ImConnection;
import com.android.im.engine.ImErrorInfo;
import com.android.im.plugin.BrandingResourceIDs;
import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.ImageView;

public class SigningInActivity extends Activity {
    private static final String SYNC_SETTINGS_ACTION = "android.settings.SYNC_SETTINGS";
    private static final String SYNC_SETTINGS_CATEGORY = "android.intent.category.DEFAULT";

    private IImConnection mConn;
    private IConnectionListener mListener;
    private SimpleAlertHandler mHandler;
    private ImApp mApp;
    private long mProviderId;
    private long mAccountId;
    private String mProviderName;

    private String mUserName;
    private String mPassword;

    private String mToAddress;

    protected static final int ID_CANCEL_SIGNIN = Menu.FIRST + 1;

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        //setTheme(android.R.style.Theme_Dialog);
        getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
        setContentView(R.layout.signing_in_activity);
        Intent intent = getIntent();
        mToAddress = intent.getStringExtra(ImApp.EXTRA_INTENT_SEND_TO_USER);

        Uri data = intent.getData();
        if (data == null) {
            if(Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
                log("Need account data to sign in");
            }
            finish();
            return;
        }
        ContentResolver cr = getContentResolver();
        Cursor c = cr.query(data, null, null, null, null);
        if (c == null) {
            if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
                log("Query fail:" + data);
            }
            finish();
            return;
        }
        if (!c.moveToFirst()) {
            if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
                log("No data for " + data);
            }
            c.close();
            finish();
            return;
        }

        mProviderId = c.getLong(c.getColumnIndexOrThrow(Imps.Account.PROVIDER));
        mAccountId = c.getLong(c.getColumnIndexOrThrow(Imps.Account._ID));
        mUserName = c.getString(c.getColumnIndexOrThrow(Imps.Account.USERNAME));
        String pwExtra = intent.getStringExtra(ImApp.EXTRA_INTENT_PASSWORD);
        mPassword = pwExtra != null ? pwExtra
                : c.getString(c.getColumnIndexOrThrow(Imps.Account.PASSWORD));
        final boolean isActive = c.getInt(c.getColumnIndexOrThrow(Imps.Account.ACTIVE)) == 1;

        c.close();
        mApp = ImApp.getApplication(this);
        final ProviderDef provider = mApp.getProvider(mProviderId);
        mProviderName = provider.mName;

        BrandingResources brandingRes = mApp.getBrandingResource(mProviderId);
        getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
                brandingRes.getDrawable(BrandingResourceIDs.DRAWABLE_LOGO));

        setTitle(getResources().getString(R.string.signing_in_to,
                provider.mFullName));

        ImageView splash = (ImageView)findViewById(R.id.splashscr);
        splash.setImageDrawable(brandingRes.getDrawable(
                BrandingResourceIDs.DRAWABLE_SPLASH_SCREEN));

        mHandler = new SimpleAlertHandler(this);
        mListener = new MyConnectionListener(mHandler);

        mApp.callWhenServiceConnected(mHandler, new Runnable() {
            public void run() {
                if (mApp.serviceConnected()) {
                    if (!isActive) {
                        activateAccount(mProviderId, mAccountId);
                    }
                    signInAccount();
                }
            }
        });

        // assume we can sign in successfully.
        setResult(RESULT_OK);
    }

    @Override
    protected void onRestart() {
        super.onRestart();

        if (mApp.serviceConnected() && mApp.isBackgroundDataEnabled()) {
            signInAccount();
        } else {
            if(Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
                log("onRestart: service disconnected or background data disabled...");
            }
            setResult(RESULT_CANCELED);
            finish();
        }
    }

    void signInAccount() {
        try {
            IImConnection conn = mApp.getConnection(mProviderId);
            if (conn != null) {
                mConn = conn;
                // register listener before get state so that we won't miss
                // any state change event.
                conn.registerConnectionListener(mListener);
                int state = conn.getState();
                if (state != ImConnection.LOGGING_IN) {
                    // already signed in or failed
                    conn.unregisterConnectionListener(mListener);
                    handleConnectionEvent(state, null);
                }
            } else {
                if (mApp.isBackgroundDataEnabled()) {
                    mConn = mApp.createConnection(mProviderId);
                    mConn.registerConnectionListener(mListener);
                    mConn.login(mAccountId, mUserName, mPassword, true);
                } else {
                    promptForBackgroundDataSetting();
                    return;
                }
            }

        } catch (RemoteException e) {
            mHandler.showServiceErrorAlert();
            finish();
        }
    }

    private void activateAccount(long providerId, long accountId) {
        // Update the active value. We restrict to only one active
        // account per provider right now, so update all accounts of
        // this provider to inactive first and then update this
        // account to active.
        ContentValues values = new ContentValues(1);
        values.put(Imps.Account.ACTIVE, 0);
        ContentResolver cr = getContentResolver();
        cr.update(Imps.Account.CONTENT_URI, values,
                Imps.Account.PROVIDER + "=" + providerId, null);

        values.put(Imps.Account.ACTIVE, 1);
        cr.update(ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId),
                values, null, null);
    }

    @Override
    protected void onStop() {
        super.onStop();

        if (mApp != null) {
            mApp.removePendingCall(mHandler);
        }
        if (mConn != null) {
            try {
                if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
                    log("unregisterConnectonListener");
                }
                mConn.unregisterConnectionListener(mListener);
            } catch (RemoteException e) {
                Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared!");
            }
        }
        // When background data is enabled, we don't want this activity in the backlist
        // so we always call finish() when we leave signing in screen. Otherwise, we
        // don't finish since we need to keep signing in if user choose to enable background.
        if (mApp.isBackgroundDataEnabled()) {
            finish();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, ID_CANCEL_SIGNIN, 0, R.string.menu_cancel_signin)
            .setIcon(android.R.drawable.ic_menu_close_clear_cancel);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == ID_CANCEL_SIGNIN) {
            if (mConn != null) {
                try {
                    if (mConn.getState() == ImConnection.LOGGING_IN) {
                        if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
                            log("Cancelling sign in");
                        }
                        mConn.logout();
                        finish();
                    }
                } catch (RemoteException e) {
                    Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared!");
                }
            }
            return true;
        } else {
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * Popup a dialog to ask the user whether he/she wants to enable
     * background connection to continue. If yes, enable the setting
     * and broadcast the change. Otherwise, quit the signing in window
     * immediately.
     */
    private void promptForBackgroundDataSetting() {
        new AlertDialog.Builder(SigningInActivity.this)
            .setTitle(R.string.bg_data_prompt_title)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setMessage(getString(R.string.bg_data_prompt_message, mProviderName))
            .setPositiveButton(R.string.bg_data_prompt_ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    Intent intent = new Intent(SYNC_SETTINGS_ACTION);
                    intent.addCategory(SYNC_SETTINGS_CATEGORY);
                    startActivity(intent);
                }
             })
            .setNegativeButton(R.string.bg_data_prompt_cancel,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        setResult(RESULT_CANCELED);
                        finish();
                    }
             })
            .show();
    }

    void handleConnectionEvent(int state, ImErrorInfo error) {
        if (isFinishing()) {
            return;
        }

        if (state == ImConnection.LOGGED_IN) {
            // sign in successfully, finish and switch to contact list
            finish();
            try {
                Intent intent;
                long accountId = mConn.getAccountId();

                if (mToAddress != null) {
                    IChatSessionManager manager = mConn.getChatSessionManager();
                    IChatSession session = manager.getChatSession(mToAddress);
                    if(session == null) {
                        session = manager.createChatSession(mToAddress);
                    }
                    Uri data = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, session.getId());
                    intent = new Intent(Intent.ACTION_VIEW, data);
                    intent.putExtra("from", mToAddress);
                    intent.putExtra("providerId", mProviderId);
                    intent.putExtra("accountId", accountId);
                    intent.addCategory(ImApp.IMPS_CATEGORY);

                } else {
                    intent = new Intent(this, ContactListActivity.class);
                    intent.putExtra(ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID, accountId);
                }
                startActivity(intent);
            } catch (RemoteException e) {
                // Ouch!  Service died!  We'll just disappear.
                Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared while signing in!");
            }
        } else if (state == ImConnection.DISCONNECTED) {
            // sign in failed
            Resources r = getResources();
            new AlertDialog.Builder(this)
                .setTitle(R.string.error)
                .setMessage(r.getString(R.string.login_service_failed, mProviderName,
                            error == null? "": ErrorResUtils.getErrorRes(r, error.getCode())))
                .setPositiveButton(R.string.ok,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                                setResult(RESULT_CANCELED);
                                finish();
                            }
                        })
                .setCancelable(false)
                .show();
        }
    }

    private static final void log(String msg) {
        Log.d(ImApp.LOG_TAG, "<SigningInActivity>" + msg);
    }

    private final class MyConnectionListener extends ConnectionListenerAdapter {
        MyConnectionListener(Handler handler) {
            super(handler);
        }

        @Override
        public void onConnectionStateChange(IImConnection connection,
                int state, ImErrorInfo error) {
            handleConnectionEvent(state, error);
        }
    }
}
