/*
 * 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 com.android.settings;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;

import java.text.Collator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 * Displays a list of {@link AppWidgetProviderInfo} widgets, along with any
 * injected special widgets specified through
 * {@link AppWidgetManager#EXTRA_CUSTOM_INFO} and
 * {@link AppWidgetManager#EXTRA_CUSTOM_EXTRAS}.
 * <p>
 * When an installed {@link AppWidgetProviderInfo} is selected, this activity
 * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID},
 * otherwise it will return the requested extras.
 */
public class AppWidgetPickActivity extends ActivityPicker {
    private static final String TAG = "AppWidgetPickActivity";
    private static final boolean LOGD = false;

    private PackageManager mPackageManager;
    private AppWidgetManager mAppWidgetManager;
    
    /**
     * The allocated {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that this
     * activity is binding.
     */
    private int mAppWidgetId;
    
    @Override
    public void onCreate(Bundle icicle) {
        mPackageManager = getPackageManager();
        mAppWidgetManager = AppWidgetManager.getInstance(this);
        
        super.onCreate(icicle);
        
        // Set default return data
        setResultData(RESULT_CANCELED, null);
        
        // Read the appWidgetId passed our direction, otherwise bail if not found
        final Intent intent = getIntent();
        if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        } else {
            finish();
        }
    }
    
    /**
     * Create list entries for any custom widgets requested through
     * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}.
     */
    void putCustomAppWidgets(List<PickAdapter.Item> items) {
        final Bundle extras = getIntent().getExtras();
        
        // get and validate the extras they gave us
        ArrayList<AppWidgetProviderInfo> customInfo = null;
        ArrayList<Bundle> customExtras = null;
        try_custom_items: {
            customInfo = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_INFO);
            if (customInfo == null || customInfo.size() == 0) {
                Log.i(TAG, "EXTRA_CUSTOM_INFO not present.");
                break try_custom_items;
            }

            int customInfoSize = customInfo.size();
            for (int i=0; i<customInfoSize; i++) {
                Parcelable p = customInfo.get(i);
                if (p == null || !(p instanceof AppWidgetProviderInfo)) {
                    customInfo = null;
                    Log.e(TAG, "error using EXTRA_CUSTOM_INFO index=" + i);
                    break try_custom_items;
                }
            }

            customExtras = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_EXTRAS);
            if (customExtras == null) {
                customInfo = null;
                Log.e(TAG, "EXTRA_CUSTOM_INFO without EXTRA_CUSTOM_EXTRAS");
                break try_custom_items;
            }

            int customExtrasSize = customExtras.size();
            if (customInfoSize != customExtrasSize) {
                Log.e(TAG, "list size mismatch: EXTRA_CUSTOM_INFO: " + customInfoSize
                        + " EXTRA_CUSTOM_EXTRAS: " + customExtrasSize);
                break try_custom_items;
            }


            for (int i=0; i<customExtrasSize; i++) {
                Parcelable p = customExtras.get(i);
                if (p == null || !(p instanceof Bundle)) {
                    customInfo = null;
                    customExtras = null;
                    Log.e(TAG, "error using EXTRA_CUSTOM_EXTRAS index=" + i);
                    break try_custom_items;
                }
            }
        }

        if (LOGD) Log.d(TAG, "Using " + customInfo.size() + " custom items");
        putAppWidgetItems(customInfo, customExtras, items);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void onClick(DialogInterface dialog, int which) {
        Intent intent = getIntentForPosition(which);
        
        int result;
        if (intent.getExtras() != null) {
            // If there are any extras, it's because this entry is custom.
            // Don't try to bind it, just pass it back to the app.
            setResultData(RESULT_OK, intent);
        } else {
            try {
                mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent());
                result = RESULT_OK;
            } catch (IllegalArgumentException e) {
                // This is thrown if they're already bound, or otherwise somehow
                // bogus.  Set the result to canceled, and exit.  The app *should*
                // clean up at this point.  We could pass the error along, but
                // it's not clear that that's useful -- the widget will simply not
                // appear.
                result = RESULT_CANCELED;
            }
            setResultData(result, null);
        }
        finish();
    }

    /**
     * Create list entries for the given {@link AppWidgetProviderInfo} widgets,
     * inserting extras if provided.
     */
    void putAppWidgetItems(List<AppWidgetProviderInfo> appWidgets,
            List<Bundle> customExtras, List<PickAdapter.Item> items) {
        if (appWidgets == null) return;
        final int size = appWidgets.size();
        for (int i = 0; i < size; i++) {
            AppWidgetProviderInfo info = appWidgets.get(i);
            
            CharSequence label = info.label;
            Drawable icon = null;

            if (info.icon != 0) {
                icon = mPackageManager.getDrawable(info.provider.getPackageName(), info.icon, null);
                if (icon == null) {
                    Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
                            + " for provider: " + info.provider);
                }
            }
            
            PickAdapter.Item item = new PickAdapter.Item(this, label, icon);
            
            item.packageName = info.provider.getPackageName();
            item.className = info.provider.getClassName();
            
            if (customExtras != null) {
                item.extras = customExtras.get(i);
            }
            
            items.add(item);
        }
    }
    
    /**
     * Build and return list of items to be shown in dialog. This will mix both
     * installed {@link AppWidgetProviderInfo} and those provided through
     * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}, sorting them alphabetically.
     */
    @Override
    protected List<PickAdapter.Item> getItems() {
        List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>();
        
        putInstalledAppWidgets(items);
        putCustomAppWidgets(items);
        
        // Sort all items together by label
        Collections.sort(items, new Comparator<PickAdapter.Item>() {
                Collator mCollator = Collator.getInstance();
                public int compare(PickAdapter.Item lhs, PickAdapter.Item rhs) {
                    return mCollator.compare(lhs.label, rhs.label);
                }
            });

        return items;
    }

    /**
     * Create list entries for installed {@link AppWidgetProviderInfo} widgets.
     */
    void putInstalledAppWidgets(List<PickAdapter.Item> items) {
        List<AppWidgetProviderInfo> installed = mAppWidgetManager.getInstalledProviders();
        putAppWidgetItems(installed, null, items);
    }

    /**
     * Convenience method for setting the result code and intent. This method
     * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that
     * most hosts expect returned.
     */
    void setResultData(int code, Intent intent) {
        Intent result = intent != null ? intent : new Intent();
        result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
        setResult(code, result);
    }
}
