/*
 * Copyright (C) 2010 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.systemui.recent;

import com.android.systemui.R;

import com.android.ex.carousel.CarouselView;
import com.android.ex.carousel.CarouselViewHelper;
import com.android.ex.carousel.CarouselRS.CarouselCallback;
import com.android.ex.carousel.CarouselViewHelper.DetailTextureParameters;

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

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.IThumbnailReceiver;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.PorterDuff;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.Drawable;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.MeasureSpec;
import android.widget.TextView;

public class RecentApplicationsActivity extends Activity {
    private static final String TAG = "RecentApplicationsActivity";
    private static boolean DBG = false;
    private static final int CARD_SLOTS = 56;
    private static final int VISIBLE_SLOTS = 7;
    private static final int MAX_TASKS = VISIBLE_SLOTS * 2;

    // TODO: these should be configurable
    private static final int DETAIL_TEXTURE_MAX_WIDTH = 200;
    private static final int DETAIL_TEXTURE_MAX_HEIGHT = 80;
    private static final int TEXTURE_WIDTH = 256;
    private static final int TEXTURE_HEIGHT = 256;

    private ActivityManager mActivityManager;
    private List<RunningTaskInfo> mRunningTaskList;
    private boolean mPortraitMode = true;
    private ArrayList<ActivityDescription> mActivityDescriptions
            = new ArrayList<ActivityDescription>();
    private CarouselView mCarouselView;
    private LocalCarouselViewHelper mHelper;
    private View mNoRecentsView;
    private Bitmap mLoadingBitmap;
    private Bitmap mRecentOverlay;
    private boolean mHidden = false;
    private boolean mHiding = false;
    private DetailInfo mDetailInfo;

    /**
     * This class is a container for all items associated with the DetailView we'll
     * be drawing to a bitmap and sending to Carousel.
     *
     */
    static final class DetailInfo {
        public DetailInfo(View _view, TextView _title, TextView _desc) {
            view = _view;
            title = _title;
            description = _desc;
        }

        /**
         * Draws view into the given bitmap, if provided
         * @param bitmap
         */
        public Bitmap draw(Bitmap bitmap) {
            resizeView(view, DETAIL_TEXTURE_MAX_WIDTH, DETAIL_TEXTURE_MAX_HEIGHT);
            int desiredWidth = view.getWidth();
            int desiredHeight = view.getHeight();
            if (bitmap == null || desiredWidth != bitmap.getWidth()
                    || desiredHeight != bitmap.getHeight()) {
                bitmap = Bitmap.createBitmap(desiredWidth, desiredHeight, Config.ARGB_8888);
            }
            Canvas canvas = new Canvas(bitmap);
            view.draw(canvas);
            return bitmap;
        }

        /**
         * Force a layout pass on the given view.
         */
        private void resizeView(View view, int maxWidth, int maxHeight) {
            int widthSpec = MeasureSpec.getMode(MeasureSpec.AT_MOST)
                    | MeasureSpec.getSize(maxWidth);
            int heightSpec = MeasureSpec.getMode(MeasureSpec.AT_MOST)
                    | MeasureSpec.getSize(maxHeight);
            view.measure(widthSpec, heightSpec);
            view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
            Log.v(TAG, "RESIZED VIEW: " + view.getWidth() + ", " + view.getHeight());
        }

        public View view;
        public TextView title;
        public TextView description;
    }

    static class ActivityDescription {
        int id;
        Bitmap thumbnail; // generated by Activity.onCreateThumbnail()
        Drawable icon; // application package icon
        String label; // application package label
        CharSequence description; // generated by Activity.onCreateDescription()
        Intent intent; // launch intent for application
        Matrix matrix; // arbitrary rotation matrix to correct orientation
        int position; // position in list

        public ActivityDescription(Bitmap _thumbnail,
                Drawable _icon, String _label, String _desc, int _id, int _pos)
        {
            thumbnail = _thumbnail;
            icon = _icon;
            label = _label;
            description = _desc;
            id = _id;
            position = _pos;
        }

        public void clear() {
            icon = null;
            thumbnail = null;
            label = null;
            description = null;
            intent = null;
            matrix = null;
            id = -1;
            position = -1;
        }
    };

    private ActivityDescription findActivityDescription(int id) {
        for (int i = 0; i < mActivityDescriptions.size(); i++) {
            ActivityDescription item = mActivityDescriptions.get(i);
            if (item != null && item.id == id) {
                return item;
            }
        }
        return null;
    }

    private class LocalCarouselViewHelper extends CarouselViewHelper {
        private DetailTextureParameters mDetailParams = new DetailTextureParameters(10.0f, 20.0f);

        public LocalCarouselViewHelper(Context context) {
            super(context);
        }

        @Override
        public DetailTextureParameters getDetailTextureParameters(int id) {
            return mDetailParams;
        }

        public void onCardSelected(int n) {
            if (n < mActivityDescriptions.size()) {
                ActivityDescription item = mActivityDescriptions.get(n);
                if (item.id >= 0) {
                    // This is an active task; it should just go to the foreground.
                    final ActivityManager am = (ActivityManager)
                            getSystemService(Context.ACTIVITY_SERVICE);
                    am.moveTaskToFront(item.id, ActivityManager.MOVE_TASK_WITH_HOME);
                } else if (item.intent != null) {
                    // prepare a launch intent and send it
                    item.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
                            | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
                    try {
                        if (DBG) Log.v(TAG, "Starting intent " + item.intent);
                        startActivity(item.intent);
                        overridePendingTransition(R.anim.recent_app_enter, R.anim.recent_app_leave);
                    } catch (ActivityNotFoundException e) {
                        if (DBG) Log.w("Recent", "Unable to launch recent task", e);
                    }
                    finish();
                }
            }
        }

        @Override
        public Bitmap getTexture(final int id) {
            if (DBG) Log.v(TAG, "onRequestTexture(" + id + ")");
            ActivityDescription info;
            synchronized(mActivityDescriptions) {
                info = mActivityDescriptions.get(id);
            }
            Bitmap bitmap = null;
            if (info != null) {
                bitmap = compositeBitmap(info);
            }
            return bitmap;
        }

        @Override
        public Bitmap getDetailTexture(int n) {
            Bitmap bitmap = null;
            if (n < mActivityDescriptions.size()) {
                ActivityDescription item = mActivityDescriptions.get(n);
                mDetailInfo.title.setText(item.label);
                mDetailInfo.description.setText(item.description);
                bitmap = mDetailInfo.draw(null);
            }
            return bitmap;
        }
    };

    private Bitmap compositeBitmap(ActivityDescription info) {
        final int targetWidth = TEXTURE_WIDTH;
        final int targetHeight = TEXTURE_HEIGHT;
        final int border = 3; // inset along the edge for thumnnail content
        final int overlap = 1; // how many pixels of overlap between border and thumbnail
        final Resources res = getResources();
        if (mRecentOverlay == null) {
            mRecentOverlay = BitmapFactory.decodeResource(res, R.drawable.recent_overlay);
        }

        // Create a bitmap of the proper size/format and set the canvas to draw to it
        final Bitmap result = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(result);
        canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, Paint.FILTER_BITMAP_FLAG));
        Paint paint = new Paint();
        paint.setFilterBitmap(false);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
        canvas.save();
        if (info.thumbnail != null) {
            // Draw the thumbnail
            int sourceWidth = targetWidth - 2 * (border - overlap);
            int sourceHeight = targetHeight - 2 * (border - overlap);
            final float scaleX = (float) sourceWidth / info.thumbnail.getWidth();
            final float scaleY = (float) sourceHeight / info.thumbnail.getHeight();
            canvas.translate(border * 0.5f, border * 0.5f);
            canvas.scale(scaleX, scaleY);
            canvas.drawBitmap(info.thumbnail, 0, 0, paint);
        } else {
            // Draw the Loading bitmap placeholder, TODO: Remove when RS handles blending
            final float scaleX = (float) targetWidth / mLoadingBitmap.getWidth();
            final float scaleY = (float) targetHeight / mLoadingBitmap.getHeight();
            canvas.scale(scaleX, scaleY);
            canvas.drawBitmap(mLoadingBitmap, 0, 0, paint);
        }
        canvas.restore();

        // Draw overlay
        canvas.save();
        final float scaleOverlayX = (float) targetWidth / mRecentOverlay.getWidth();
        final float scaleOverlayY = (float) targetHeight / mRecentOverlay.getHeight();
        canvas.scale(scaleOverlayX, scaleOverlayY);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
        canvas.drawBitmap(mRecentOverlay, 0, 0, paint);
        canvas.restore();

        // Draw icon
        if (info.icon != null) {
            canvas.save();
            info.icon.draw(canvas);
            canvas.restore();
        }

        return result;
    }

    private final IThumbnailReceiver mThumbnailReceiver = new IThumbnailReceiver.Stub() {

        public void finished() throws RemoteException {

        }

        public void newThumbnail(final int id, final Bitmap bitmap, CharSequence description)
                throws RemoteException {
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();
            if (DBG) Log.v(TAG, "New thumbnail for id=" + id + ", dimensions=" + w + "x" + h
                    + " description '" + description + "'");
            ActivityDescription info = findActivityDescription(id);
            if (info != null) {
                info.thumbnail = bitmap;
                info.description = description;
                final int thumbWidth = bitmap.getWidth();
                final int thumbHeight = bitmap.getHeight();
                if ((mPortraitMode && thumbWidth > thumbHeight)
                        || (!mPortraitMode && thumbWidth < thumbHeight)) {
                    Matrix matrix = new Matrix();
                    matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2);
                    info.matrix = matrix;
                } else {
                    info.matrix = null;
                }
                // Force Carousel to request new textures for this item.
                mCarouselView.setTextureForItem(info.position, null);
                mCarouselView.setDetailTextureForItem(info.position, 0, 0, 0, 0, null);
            } else {
                if (DBG) Log.v(TAG, "Can't find view for id " + id);
            }
        }
    };

    /**
     * We never really finish() RecentApplicationsActivity, since we don't want to
     * get destroyed and pay the start-up cost to restart it.
     */
    @Override
    public void finish() {
        moveTaskToBack(true);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        mHidden = !mHidden;
        if (mHidden) {
            mHiding = true;
            moveTaskToBack(true);
        } else {
            mHiding = false;
        }
        super.onNewIntent(intent);
    }

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

        final Resources res = getResources();
        final View decorView = getWindow().getDecorView();

        getWindow().getDecorView().setBackgroundColor(0x80000000);

        if (mCarouselView == null) {
            long t = System.currentTimeMillis();
            setContentView(R.layout.recent_apps_activity);
            long elapsed = System.currentTimeMillis() - t;
            Log.v(TAG, "Recents layout took " + elapsed + "ms to load");
            mLoadingBitmap = BitmapFactory.decodeResource(res, R.drawable.recent_rez_border);
            mCarouselView = (CarouselView)findViewById(R.id.carousel);
            mHelper = new LocalCarouselViewHelper(this);
            mHelper.setCarouselView(mCarouselView);

            mCarouselView.setSlotCount(CARD_SLOTS);
            mCarouselView.setVisibleSlots(VISIBLE_SLOTS);
            mCarouselView.createCards(0);
            mCarouselView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS));
            mCarouselView.setDefaultBitmap(mLoadingBitmap);
            mCarouselView.setLoadingBitmap(mLoadingBitmap);
            mCarouselView.setRezInCardCount(3.0f);
            mCarouselView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

            mNoRecentsView = (View) findViewById(R.id.no_applications_message);

            mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
            mPortraitMode = decorView.getHeight() > decorView.getWidth();

            // Load detail view which will be used to render text
            View detail = getLayoutInflater().inflate(R.layout.recents_detail_view, null);
            TextView title = (TextView) detail.findViewById(R.id.app_title);
            TextView description = (TextView) detail.findViewById(R.id.app_description);
            mDetailInfo = new DetailInfo(detail, title, description);

            refresh();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        refresh();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mPortraitMode = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT;
        if (DBG) Log.v(TAG, "CONFIG CHANGE, mPortraitMode = " + mPortraitMode);
        refresh();
    }

    void updateRunningTasks() {
        mRunningTaskList = mActivityManager.getRunningTasks(MAX_TASKS,
                ActivityManager.TASKS_GET_THUMBNAILS, mThumbnailReceiver);
        if (DBG) Log.v(TAG, "Portrait: " + mPortraitMode);
        for (RunningTaskInfo r : mRunningTaskList) {
            if (r.thumbnail != null) {
                int thumbWidth = r.thumbnail.getWidth();
                int thumbHeight = r.thumbnail.getHeight();
                if (DBG) Log.v(TAG, "Got thumbnail " + thumbWidth + "x" + thumbHeight);
                ActivityDescription desc = findActivityDescription(r.id);
                if (desc != null) {
                    desc.thumbnail = r.thumbnail;
                    desc.description = r.description;
                    if ((mPortraitMode && thumbWidth > thumbHeight)
                            || (!mPortraitMode && thumbWidth < thumbHeight)) {
                        Matrix matrix = new Matrix();
                        matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2);
                        desc.matrix = matrix;
                    }
                } else {
                    if (DBG) Log.v(TAG, "Couldn't find ActivityDesc for id=" + r.id);
                }
            } else {
                if (DBG) Log.v(TAG, "*** RUNNING THUMBNAIL WAS NULL ***");
            }
        }
    }

    private void updateRecentTasks() {
        final PackageManager pm = getPackageManager();
        final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

        final List<ActivityManager.RecentTaskInfo> recentTasks =
                am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE
                        | ActivityManager.TASKS_GET_THUMBNAILS);

        ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
                    .resolveActivityInfo(pm, 0);

        // IconUtilities iconUtilities = new IconUtilities(this); // FIXME

        int numTasks = recentTasks.size();
        mActivityDescriptions.clear();
        for (int i = 0, index = 0; i < numTasks && (index < MAX_TASKS); ++i) {
            final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);

            Intent intent = new Intent(recentInfo.baseIntent);
            if (recentInfo.origActivity != null) {
                intent.setComponent(recentInfo.origActivity);
            }

            // Skip the current home activity.
            if (homeInfo != null
                    && homeInfo.packageName.equals(intent.getComponent().getPackageName())
                    && homeInfo.name.equals(intent.getComponent().getClassName())) {
                continue;
            }

            intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                    | Intent.FLAG_ACTIVITY_NEW_TASK);
            final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
            if (resolveInfo != null) {
                final ActivityInfo info = resolveInfo.activityInfo;
                final String title = info.loadLabel(pm).toString();
                Drawable icon = info.loadIcon(pm);

                int id = recentTasks.get(i).id;
                if (id != -1 && title != null && title.length() > 0 && icon != null) {
                    // icon = null; FIXME: iconUtilities.createIconDrawable(icon);
                    ActivityDescription item = new ActivityDescription(
                            null, icon, title, null, id, index);
                    item.intent = intent;
                    mActivityDescriptions.add(item);
                    if (DBG) Log.v(TAG, "Added item[" + index
                            + "], id=" + item.id
                            + ", title=" + item.label);
                    ++index;
                } else {
                    if (DBG) Log.v(TAG, "SKIPPING item " + id);
                }
            }
        }
    }

    private final Runnable mRefreshRunnable = new Runnable() {
        public void run() {
            updateRecentTasks();
            updateRunningTasks();
            showCarousel(mActivityDescriptions.size() > 0);
        }
    };

    private void showCarousel(boolean show) {
        if (show) {
            mCarouselView.createCards(mActivityDescriptions.size());
            for (int i = 1; i < mActivityDescriptions.size(); i++) {
                // Force Carousel to update textures. Note we don't do this for the first item,
                // since it will be updated when mThumbnailReceiver returns a thumbnail.
                // TODO: only do this for apps that have changed.
                mCarouselView.setTextureForItem(i, null);
                mCarouselView.setDetailTextureForItem(i, 0, 0, 0, 0, null);
            }
            // Make carousel visible
            mNoRecentsView.setVisibility(View.GONE);
            mCarouselView.setVisibility(View.VISIBLE);
            mCarouselView.createCards(mActivityDescriptions.size());
        } else {
            // show "No Recent Tasks"
            mNoRecentsView.setVisibility(View.VISIBLE);
            mCarouselView.setVisibility(View.GONE);
        }
    }

    private void refresh() {
        if (!mHiding && mCarouselView != null) {
            // Don't update the view now. Instead, post a request so it happens next time
            // we reach the looper after a delay. This way we can fold multiple refreshes
            // into just the latest.
            mCarouselView.removeCallbacks(mRefreshRunnable);
            mCarouselView.postDelayed(mRefreshRunnable, 50);
        }
    }
}
