//
// Copyright 2011 Thomas Gumprecht, Robert Jacob, Thomas Pieronczyk
//
// 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 net.sourcewalker.garanbot.account;

import net.sourcewalker.garanbot.R;
import net.sourcewalker.garanbot.api.AuthenticationException;
import net.sourcewalker.garanbot.api.ClientException;
import net.sourcewalker.garanbot.api.GaranboClient;
import net.sourcewalker.garanbot.api.User;
import net.sourcewalker.garanbot.data.GaranbotDBMetaData;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.content.ContentResolver;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

/**
 * This activity presents a simple login screen to the user. When he clicks
 * Login the entered data is validated and if it is correct the next activity is
 * displayed. If the login was successful this activity should not be reachable
 * using the back button. This activity will be launched from the
 * {@link AccountManager} once the account management has been implemented.
 * 
 * @author Xperimental
 */
public class LoginActivity extends AccountAuthenticatorActivity implements
        OnClickListener {

    public static final String ACTION_ERROR = LoginActivity.class.getName()
            + ".ERROR";

    public static final String TAG = "LoginActivity";

    private String accountType;
    private AccountManager accountManager;
    private Button loginButton;
    private Button cancelButton;
    private Button registerButton;
    private EditText usernameField;
    private EditText passwordField;

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.activity_login);

        accountType = getString(R.string.account_type);
        accountManager = AccountManager.get(this);

        loginButton = (Button) findViewById(R.id.login_ok);
        loginButton.setOnClickListener(this);
        cancelButton = (Button) findViewById(R.id.login_cancel);
        cancelButton.setOnClickListener(this);
        registerButton = (Button) findViewById(R.id.login_register);
        registerButton.setOnClickListener(this);
        usernameField = (EditText) findViewById(R.id.login_username);
        passwordField = (EditText) findViewById(R.id.login_password);

        if (ACTION_ERROR.equals(getIntent().getAction())) {
            final Bundle extras = getIntent().getExtras();
            if (extras != null) {
                final String message = extras
                        .getString(AccountManager.KEY_ERROR_MESSAGE);
                Toast.makeText(this, message, Toast.LENGTH_LONG).show();
            }
            finish();
        }
    }

    /**
     * Enable or disable interactive GUI elements in activity.
     * 
     * @param enabled
     *            If true, elements will be enabled.
     */
    protected void enableGui(final boolean enabled) {
        loginButton.setEnabled(enabled);
        cancelButton.setEnabled(enabled);
        registerButton.setEnabled(enabled);
        usernameField.setEnabled(enabled);
        passwordField.setEnabled(enabled);
    }

    /**
     * Create the account in the account manager.
     * 
     * @param username
     *            Username of new account.
     * @param password
     *            Password of new account.
     */
    public void createAccount(final String username, final String password) {
        final Account account = new Account(username, accountType);
        final boolean created = accountManager.addAccountExplicitly(account,
                password, null);
        if (created) {
            final Bundle result = new Bundle();
            result.putString(AccountManager.KEY_ACCOUNT_NAME, username);
            result.putString(AccountManager.KEY_ACCOUNT_TYPE, accountType);
            setAccountAuthenticatorResult(result);

            ContentResolver.setSyncAutomatically(account,
                    GaranbotDBMetaData.AUTHORITY, true);
            finish();
        } else {
            Toast.makeText(this, R.string.toast_account_createfailed,
                    Toast.LENGTH_LONG).show();
        }
    }

    /*
     * (non-Javadoc)
     * @see android.view.View.OnClickListener#onClick(android.view.View)
     */
    public void onClick(final View v) {
        switch (v.getId()) {
        case R.id.login_ok:
            final String username = usernameField.getText().toString();
            final String password = passwordField.getText().toString();

            final CredentialsTestTask task = new CredentialsTestTask();
            task.execute(username, password);
            break;
        case R.id.login_cancel:
            finish();
            break;
        case R.id.login_register:
            final Intent registerActivity = new Intent(this,
                    RegisterActivity.class);
            startActivity(registerActivity);
            break;
        default:
            throw new IllegalArgumentException("Unknown view clicked: " + v);
        }
    }

    private class CredentialsTestTask extends
            AsyncTask<String, Void, LoginParcel> {

        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#onPreExecute()
         */
        @Override
        protected void onPreExecute() {
            setProgressBarIndeterminateVisibility(true);
            enableGui(false);
        }

        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#doInBackground(Params[])
         */
        @Override
        protected LoginParcel doInBackground(final String... params) {
            final String username = params[0];
            final String password = params[1];
            final GaranboClient client = new GaranboClient(username, password);
            Boolean result;
            try {
                final User serverUser = client.user().get();
                result = username.equalsIgnoreCase(serverUser.getUsername());
            } catch (final AuthenticationException e) {
                // Wrong password etc.
                result = false;
            } catch (final ClientException e) {
                // Other reason for failing (e.g. network).
                Log.e(TAG, "Error while logging in: " + e.getMessage());
                result = false;
            }
            return new LoginParcel(username, password, result);
        }

        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
         */
        @Override
        protected void onPostExecute(final LoginParcel result) {
            setProgressBarIndeterminateVisibility(false);
            enableGui(true);

            if (result.successful) {
                createAccount(result.username, result.password);
            } else {
                Toast.makeText(LoginActivity.this, R.string.toast_loginfailed,
                        Toast.LENGTH_LONG).show();
            }
        }

    }

}
