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

import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.LinearLayout;
import android.view.View;
import android.view.LayoutInflater;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import com.android.internal.R;

import java.io.IOException;

/**
 * @hide
 */
public class GrantCredentialsPermissionActivity extends Activity implements View.OnClickListener {
    public static final String EXTRAS_ACCOUNT = "account";
    public static final String EXTRAS_AUTH_TOKEN_LABEL = "authTokenLabel";
    public static final String EXTRAS_AUTH_TOKEN_TYPE = "authTokenType";
    public static final String EXTRAS_RESPONSE = "response";
    public static final String EXTRAS_ACCOUNT_TYPE_LABEL = "accountTypeLabel";
    public static final String EXTRAS_PACKAGES = "application";
    public static final String EXTRAS_REQUESTING_UID = "uid";
    private Account mAccount;
    private String mAuthTokenType;
    private int mUid;
    private Bundle mResultBundle = null;
    protected LayoutInflater mInflater;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.grant_credentials_permission);
        setTitle(R.string.grant_permissions_header_text);

        mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        final Bundle extras = getIntent().getExtras();
        if (extras == null) {
            // we were somehow started with bad parameters. abort the activity.
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        // Grant 'account'/'type' to mUID
        mAccount = extras.getParcelable(EXTRAS_ACCOUNT);
        mAuthTokenType = extras.getString(EXTRAS_AUTH_TOKEN_TYPE);
        mUid = extras.getInt(EXTRAS_REQUESTING_UID);
        final PackageManager pm = getPackageManager();
        final String[] packages = pm.getPackagesForUid(mUid);

        if (mAccount == null || mAuthTokenType == null || packages == null) {
            // we were somehow started with bad parameters. abort the activity.
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        String accountTypeLabel;
        try {
            accountTypeLabel = getAccountLabel(mAccount);
        } catch (IllegalArgumentException e) {
            // label or resource was missing. abort the activity.
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        final TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
        authTokenTypeView.setVisibility(View.GONE);

        final AccountManagerCallback<String> callback = new AccountManagerCallback<String>() {
            public void run(AccountManagerFuture<String> future) {
                try {
                    final String authTokenLabel = future.getResult();
                    if (!TextUtils.isEmpty(authTokenLabel)) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                if (!isFinishing()) {
                                    authTokenTypeView.setText(authTokenLabel);
                                    authTokenTypeView.setVisibility(View.VISIBLE);
                                }
                            }
                        });
                    }
                } catch (OperationCanceledException e) {
                } catch (IOException e) {
                } catch (AuthenticatorException e) {
                }
            }
        };
        AccountManager.get(this).getAuthTokenLabel(mAccount.type, mAuthTokenType, callback, null);

        findViewById(R.id.allow_button).setOnClickListener(this);
        findViewById(R.id.deny_button).setOnClickListener(this);

        LinearLayout packagesListView = (LinearLayout) findViewById(R.id.packages_list);

        for (String pkg : packages) {
            String packageLabel;
            try {
                packageLabel = pm.getApplicationLabel(pm.getApplicationInfo(pkg, 0)).toString();
            } catch (PackageManager.NameNotFoundException e) {
                packageLabel = pkg;
            }
            packagesListView.addView(newPackageView(packageLabel));
        }

        ((TextView) findViewById(R.id.account_name)).setText(mAccount.name);
        ((TextView) findViewById(R.id.account_type)).setText(accountTypeLabel);
    }

    private String getAccountLabel(Account account) {
        final AuthenticatorDescription[] authenticatorTypes =
                AccountManager.get(this).getAuthenticatorTypes();
        for (int i = 0, N = authenticatorTypes.length; i < N; i++) {
            final AuthenticatorDescription desc = authenticatorTypes[i];
            if (desc.type.equals(account.type)) {
                try {
                    return createPackageContext(desc.packageName, 0).getString(desc.labelId);
                } catch (PackageManager.NameNotFoundException e) {
                    return account.type;
                } catch (Resources.NotFoundException e) {
                    return account.type;
                }
            }
        }
        return account.type;
    }

    private View newPackageView(String packageLabel) {
        View view = mInflater.inflate(R.layout.permissions_package_list_item, null);
        ((TextView) view.findViewById(R.id.package_label)).setText(packageLabel);
        return view;
    }

    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.allow_button:
                AccountManager.get(this).updateAppPermission(mAccount, mAuthTokenType, mUid, true);
                Intent result = new Intent();
                result.putExtra("retry", true);
                setResult(RESULT_OK, result);
                setAccountAuthenticatorResult(result.getExtras());
                break;

            case R.id.deny_button:
                AccountManager.get(this).updateAppPermission(mAccount, mAuthTokenType, mUid, false);
                setResult(RESULT_CANCELED);
                break;
        }
        finish();
    }

    public final void setAccountAuthenticatorResult(Bundle result) {
        mResultBundle = result;
    }

    /**
     * Sends the result or a {@link AccountManager#ERROR_CODE_CANCELED} error if a
     * result isn't present.
     */
    public void finish() {
        Intent intent = getIntent();
        AccountAuthenticatorResponse response = intent.getParcelableExtra(EXTRAS_RESPONSE);
        if (response != null) {
            // send the result bundle back if set, otherwise send an error.
            if (mResultBundle != null) {
                response.onResult(mResultBundle);
            } else {
                response.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
            }
        }
        super.finish();
    }
}
