/*
 * Copyright (C) 2013 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.nfc.cardemulation;

import com.android.internal.R;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;

import java.util.ArrayList;
import java.util.List;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.nfc.NfcAdapter;
import android.nfc.cardemulation.ApduServiceInfo;
import android.nfc.cardemulation.CardEmulation;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class AppChooserActivity extends AlertActivity
        implements AdapterView.OnItemClickListener {

    static final String TAG = "AppChooserActivity";

    public static final String EXTRA_APDU_SERVICES = "services";
    public static final String EXTRA_CATEGORY = "category";
    public static final String EXTRA_FAILED_COMPONENT = "failed_component";

    private int mIconSize;
    private ListView mListView;
    private ListAdapter mListAdapter;
    private CardEmulation mCardEmuManager;
    private String mCategory;

    final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
    }

    protected void onCreate(Bundle savedInstanceState, String category,
            ArrayList<ApduServiceInfo> options, ComponentName failedComponent) {
        super.onCreate(savedInstanceState);
        setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert);

        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(mReceiver, filter);

        if ((options == null || options.size() == 0) && failedComponent == null) {
            Log.e(TAG, "No components passed in.");
            finish();
            return;
        }

        mCategory = category;
        boolean isPayment = CardEmulation.CATEGORY_PAYMENT.equals(mCategory);

        final NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
        mCardEmuManager = CardEmulation.getInstance(adapter);
        AlertController.AlertParams ap = mAlertParams;

        final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        mIconSize = am.getLauncherLargeIconSize();

        // Three cases:
        // 1. Failed component and no alternatives: just an OK box
        // 2. Failed component and alternatives: pick alternative
        // 3. No failed component and alternatives: pick alternative
        PackageManager pm = getPackageManager();

        CharSequence applicationLabel = "unknown";
        if (failedComponent != null) {
            try {
                ApplicationInfo info = pm.getApplicationInfo(failedComponent.getPackageName(), 0);
                applicationLabel = info.loadLabel(pm);
            } catch (NameNotFoundException e) {
            }

        }
        if (options.size() == 0 && failedComponent != null) {
            String formatString = getString(com.android.nfc.R.string.transaction_failure);
            ap.mTitle = "";
            ap.mMessage = String.format(formatString, applicationLabel);
            ap.mPositiveButtonText = getString(R.string.ok);
            setupAlert();
        } else {
            mListAdapter = new ListAdapter(this, options);
            if (failedComponent != null) {
                String formatString = getString(com.android.nfc.R.string.could_not_use_app);
                ap.mTitle = String.format(formatString, applicationLabel);
                ap.mNegativeButtonText = getString(R.string.cancel);
            } else {
                if (CardEmulation.CATEGORY_PAYMENT.equals(category)) {
                    ap.mTitle = getString(com.android.nfc.R.string.pay_with);
                } else {
                    ap.mTitle = getString(com.android.nfc.R.string.complete_with);
                }
            }
            ap.mView = getLayoutInflater().inflate(com.android.nfc.R.layout.cardemu_resolver, null);

            mListView = (ListView) ap.mView.findViewById(com.android.nfc.R.id.resolver_list);
            if (isPayment) {
                mListView.setDivider(getResources().getDrawable(android.R.color.transparent));
                int height = (int) (getResources().getDisplayMetrics().density * 16);
                mListView.setDividerHeight(height);
            } else {
                mListView.setPadding(0, 0, 0, 0);
            }
            mListView.setAdapter(mListAdapter);
            mListView.setOnItemClickListener(this);

            setupAlert();
        }
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Intent intent = getIntent();
        ArrayList<ApduServiceInfo> services = intent.getParcelableArrayListExtra(EXTRA_APDU_SERVICES);
        String category = intent.getStringExtra(EXTRA_CATEGORY);
        ComponentName failedComponent = intent.getParcelableExtra(EXTRA_FAILED_COMPONENT);
        onCreate(savedInstanceState, category, services, failedComponent);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        DisplayAppInfo info = (DisplayAppInfo) mListAdapter.getItem(position);
        mCardEmuManager.setDefaultForNextTap(info.serviceInfo.getComponent());
        Intent dialogIntent = new Intent(this, TapAgainDialog.class);
        dialogIntent.putExtra(TapAgainDialog.EXTRA_CATEGORY, mCategory);
        dialogIntent.putExtra(TapAgainDialog.EXTRA_APDU_SERVICE, info.serviceInfo);
        startActivity(dialogIntent);
        finish();
    }

    final class DisplayAppInfo {
        ApduServiceInfo serviceInfo;
        CharSequence displayLabel;
        Drawable displayIcon;
        Drawable displayBanner;

        public DisplayAppInfo(ApduServiceInfo serviceInfo, CharSequence label, Drawable icon,
                Drawable banner) {
            this.serviceInfo = serviceInfo;
            displayIcon = icon;
            displayLabel = label;
            displayBanner = banner;
        }
    }

    final class ListAdapter extends BaseAdapter {
        private final LayoutInflater mInflater;
        private final boolean mIsPayment;
        private List<DisplayAppInfo> mList;

        public ListAdapter(Context context, ArrayList<ApduServiceInfo> services) {
            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            // For each component, get the corresponding app name and icon
            PackageManager pm = getPackageManager();
            mList = new ArrayList<DisplayAppInfo>();
            mIsPayment = CardEmulation.CATEGORY_PAYMENT.equals(mCategory);
            for (ApduServiceInfo service : services) {
                CharSequence label = service.getDescription();
                if (label == null) label = service.loadLabel(pm);
                Drawable icon = service.loadIcon(pm);
                Drawable banner = null;
                if (mIsPayment) {
                    banner = service.loadBanner(pm);
                    if (banner == null) {
                        Log.e(TAG, "Not showing " + label + " because no banner specified.");
                        continue;
                    }
                }
                DisplayAppInfo info = new DisplayAppInfo(service, label, icon, banner);
                mList.add(info);
            }
        }

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public Object getItem(int position) {
            return mList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            if (convertView == null) {
                if (mIsPayment) {
                    view = mInflater.inflate(
                            com.android.nfc.R.layout.cardemu_payment_item, parent, false);
                } else {
                    view = mInflater.inflate(
                            com.android.nfc.R.layout.cardemu_item, parent, false);
                }
                final ViewHolder holder = new ViewHolder(view);
                view.setTag(holder);

            } else {
                view = convertView;
            }

            final ViewHolder holder = (ViewHolder) view.getTag();
            DisplayAppInfo appInfo = mList.get(position);
            if (mIsPayment) {
                holder.banner.setImageDrawable(appInfo.displayBanner);
            } else {
                ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
                lp.width = lp.height = mIconSize;
                holder.icon.setImageDrawable(appInfo.displayIcon);
                holder.text.setText(appInfo.displayLabel);
            }
            return view;
        }
    }

    static class ViewHolder {
        public TextView text;
        public ImageView icon;
        public ImageView banner;
        public ViewHolder(View view) {
            text = (TextView) view.findViewById(com.android.nfc.R.id.applabel);
            icon = (ImageView) view.findViewById(com.android.nfc.R.id.appicon);
            banner = (ImageView) view.findViewById(com.android.nfc.R.id.banner);
        }
    }
}