/*
 * 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.statusbar.tablet;

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

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.ActivityManager;
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.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.android.systemui.R;

public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, OnItemClickListener {
    private static final int GLOW_PADDING = 15;
    private static final String TAG = "RecentAppsPanel";
    private static final boolean DEBUG = TabletStatusBar.DEBUG;
    private static final int DISPLAY_TASKS = 20;
    private static final int MAX_TASKS = DISPLAY_TASKS + 1; // allow extra for non-apps
    private TabletStatusBar mBar;
    private ArrayList<ActivityDescription> mActivityDescriptions;
    private int mIconDpi;
    private View mRecentsScrim;
    private View mRecentsGlowView;
    private ListView mRecentsContainer;
    private CheckBox mCompatMode;
    private Bitmap mGlowBitmap;
    private boolean mShowing;
    private Choreographer mChoreo;
    private View mRecentsDismissButton;
    private ActvityDescriptionAdapter mListAdapter;
    protected int mLastVisibleItem;

    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
        String packageName; // used to override animations (see onClick())
        int position; // position in list

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

    /* package */ final static class ViewHolder {
        private ImageView thumbnailView;
        private ImageView iconView;
        private TextView labelView;
        private TextView descriptionView;
        private ActivityDescription activityDescription;
    }

    /* package */ final class ActvityDescriptionAdapter extends BaseAdapter {
        private LayoutInflater mInflater;

        public ActvityDescriptionAdapter(Context context) {
            mInflater = LayoutInflater.from(context);
        }

        public int getCount() {
            return mActivityDescriptions != null ? mActivityDescriptions.size() : 0;
        }

        public Object getItem(int position) {
            return position; // we only need the index
        }

        public long getItemId(int position) {
            return position; // we just need something unique for this position
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.status_bar_recent_item, null);
                holder = new ViewHolder();
                holder.thumbnailView = (ImageView) convertView.findViewById(R.id.app_thumbnail);
                holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
                holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
                holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            // activityId is reverse since most recent appears at the bottom...
            final int activityId = mActivityDescriptions.size() - position - 1;

            final ActivityDescription activityDescription = mActivityDescriptions.get(activityId);
            final Bitmap thumb = activityDescription.thumbnail;
            holder.thumbnailView.setImageBitmap(compositeBitmap(mGlowBitmap, thumb));
            holder.iconView.setImageDrawable(activityDescription.icon);
            holder.labelView.setText(activityDescription.label);
            holder.descriptionView.setText(activityDescription.description);
            holder.thumbnailView.setTag(activityDescription);
            holder.activityDescription = activityDescription;

            return convertView;
        }
    }

    public boolean isInContentArea(int x, int y) {
        // use mRecentsContainer's exact bounds to determine horizontal position
        final int l = mRecentsContainer.getLeft();
        final int r = mRecentsContainer.getRight();
        // use surrounding mRecentsGlowView's position in parent determine vertical bounds
        final int t = mRecentsGlowView.getTop();
        final int b = mRecentsGlowView.getBottom();
        return x >= l && x < r && y >= t && y < b;
    }

    public void show(boolean show, boolean animate) {
        if (animate) {
            if (mShowing != show) {
                mShowing = show;
                if (show) {
                    setVisibility(View.VISIBLE);
                }
                mChoreo.startAnimation(show);
            }
        } else {
            mShowing = show;
            setVisibility(show ? View.VISIBLE : View.GONE);
            mChoreo.jumpTo(show);
        }
    }

    /**
     * We need to be aligned at the bottom.  LinearLayout can't do this, so instead,
     * let LinearLayout do all the hard work, and then shift everything down to the bottom.
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mChoreo.setPanelHeight(mRecentsContainer.getHeight());
    }

    /**
     * Whether the panel is showing, or, if it's animating, whether it will be
     * when the animation is done.
     */
    public boolean isShowing() {
        return mShowing;
    }

    private static class Choreographer implements Animator.AnimatorListener {
        // should group this into a multi-property animation
        private static final int OPEN_DURATION = 136;
        private static final int CLOSE_DURATION = 250;

        boolean mVisible;
        int mPanelHeight;
        View mRootView;
        View mScrimView;
        View mContentView;
        AnimatorSet mContentAnim;

        // the panel will start to appear this many px from the end
        final int HYPERSPACE_OFFRAMP = 200;

        public Choreographer(View root, View scrim, View content) {
            mRootView = root;
            mScrimView = scrim;
            mContentView = content;
        }

        void createAnimation(boolean appearing) {
            float start, end;

            if (DEBUG) Log.e(TAG, "createAnimation()", new Exception());

            // 0: on-screen
            // height: off-screen
            float y = mContentView.getTranslationY();
            if (appearing) {
                // we want to go from near-the-top to the top, unless we're half-open in the right
                // general vicinity
                start = (y < HYPERSPACE_OFFRAMP) ? y : HYPERSPACE_OFFRAMP;
                end = 0;
            } else {
                start = y;
                end = y + HYPERSPACE_OFFRAMP;
            }

            Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
                    start, end);
            posAnim.setInterpolator(appearing
                    ? new android.view.animation.DecelerateInterpolator(2.5f)
                    : new android.view.animation.AccelerateInterpolator(2.5f));

            Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
                    mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
            glowAnim.setInterpolator(appearing
                    ? new android.view.animation.AccelerateInterpolator(1.0f)
                    : new android.view.animation.DecelerateInterpolator(1.0f));

            Animator bgAnim = ObjectAnimator.ofInt(mScrimView.getBackground(),
                    "alpha", appearing ? 0 : 255, appearing ? 255 : 0);

            mContentAnim = new AnimatorSet();
            mContentAnim
                    .play(bgAnim)
                    .with(glowAnim)
                    .with(posAnim);
            mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
            mContentAnim.addListener(this);
        }

        void startAnimation(boolean appearing) {
            if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");

            createAnimation(appearing);

            mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            mContentAnim.start();

            mVisible = appearing;
        }

        void jumpTo(boolean appearing) {
            mContentView.setTranslationY(appearing ? 0 : mPanelHeight);
        }

        public void setPanelHeight(int h) {
            if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
            mPanelHeight = h;
        }

        public void onAnimationCancel(Animator animation) {
            if (DEBUG) Slog.d(TAG, "onAnimationCancel");
            // force this to zero so we close the window
            mVisible = false;
        }

        public void onAnimationEnd(Animator animation) {
            if (DEBUG) Slog.d(TAG, "onAnimationEnd");
            if (!mVisible) {
                mRootView.setVisibility(View.GONE);
            }
            mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
            mContentAnim = null;
        }

        public void onAnimationRepeat(Animator animation) {
        }

        public void onAnimationStart(Animator animation) {
        }
    }

    public void setBar(TabletStatusBar bar) {
        mBar = bar;
    }

    public RecentAppsPanel(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RecentAppsPanel(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        Resources res = context.getResources();
        boolean xlarge = (res.getConfiguration().screenLayout
                & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;

        mIconDpi = xlarge ? DisplayMetrics.DENSITY_HIGH : res.getDisplayMetrics().densityDpi;
        mGlowBitmap = BitmapFactory.decodeResource(res, R.drawable.recents_thumbnail_bg);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // Keep track of the last visible item in the list so we can restore it
        // to the bottom when the orientation changes.
        int childCount = mRecentsContainer.getChildCount();
        if (childCount > 0) {
            mLastVisibleItem = mRecentsContainer.getFirstVisiblePosition() + childCount - 1;
            View view = mRecentsContainer.getChildAt(childCount - 1);
            final int distanceFromBottom = mRecentsContainer.getHeight() - view.getTop();
            //final int distanceFromBottom = view.getHeight() + BOTTOM_OFFSET;

            // This has to happen post-layout, so run it "in the future"
            post(new Runnable() {
                public void run() {
                    mRecentsContainer.setSelectionFromTop(mLastVisibleItem,
                            mRecentsContainer.getHeight() - distanceFromBottom);
                }
            });
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        LayoutInflater inflater = (LayoutInflater)
        mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        mRecentsContainer = (ListView) findViewById(R.id.recents_container);
        mCompatMode = (CheckBox) findViewById(R.id.recents_compat_mode);
        mCompatMode.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                final ActivityManager am = (ActivityManager)
                        mContext.getSystemService(Context.ACTIVITY_SERVICE);
                am.setFrontActivityScreenCompatMode(ActivityManager.COMPAT_MODE_TOGGLE);
                hide(true);
            }
        });
        View footer = inflater.inflate(R.layout.status_bar_recent_panel_footer,
                mRecentsContainer, false);
        mRecentsContainer.setScrollbarFadingEnabled(true);
        mRecentsContainer.addFooterView(footer, null, false);
        mRecentsContainer.setAdapter(mListAdapter = new ActvityDescriptionAdapter(mContext));
        mRecentsContainer.setOnItemClickListener(this);
        final int leftPadding = mContext.getResources()
            .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
        mRecentsContainer.setOverScrollEffectPadding(leftPadding, 0);

        mRecentsGlowView = findViewById(R.id.recents_glow);
        mRecentsScrim = (View) findViewById(R.id.recents_bg_protect);
        mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView);
        mRecentsDismissButton = findViewById(R.id.recents_dismiss_button);
        mRecentsDismissButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                hide(true);
            }
        });

        // In order to save space, we make the background texture repeat in the Y direction
        if (mRecentsScrim != null && mRecentsScrim.getBackground() instanceof BitmapDrawable) {
            ((BitmapDrawable) mRecentsScrim.getBackground()).setTileModeY(TileMode.REPEAT);
        }
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + changedView + ", " + visibility + ")");
        if (visibility == View.VISIBLE && changedView == this) {
            refreshApplicationList();
            post(new Runnable() {
                public void run() {
                    mRecentsContainer.setSelection(mActivityDescriptions.size() - 1);
                }
            });
        }
    }

    private Drawable getFullResDefaultActivityIcon() {
        return getFullResIcon(Resources.getSystem(),
                com.android.internal.R.mipmap.sym_def_app_icon);
    }

    private Drawable getFullResIcon(Resources resources, int iconId) {
        return resources.getDrawableForDensity(iconId, mIconDpi);
    }

    private Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager) {
        Resources resources;
        try {
            resources = packageManager.getResourcesForApplication(
                    info.activityInfo.applicationInfo);
        } catch (PackageManager.NameNotFoundException e) {
            resources = null;
        }
        if (resources != null) {
            int iconId = info.activityInfo.getIconResource();
            if (iconId != 0) {
                return getFullResIcon(resources, iconId);
            }
        }
        return getFullResDefaultActivityIcon();
    }

    private ArrayList<ActivityDescription> getRecentTasks() {
        ArrayList<ActivityDescription> activityDescriptions = new ArrayList<ActivityDescription>();
        final PackageManager pm = mContext.getPackageManager();
        final ActivityManager am = (ActivityManager)
                mContext.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);

        int numTasks = recentTasks.size();

        // skip the first activity - assume it's either the home screen or the current app.
        final int first = 1;
        for (int i = first, 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);
                Drawable icon = getFullResIcon(resolveInfo, pm);
                int id = recentTasks.get(i).id;
                if (title != null && title.length() > 0 && icon != null) {
                    if (DEBUG) Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title);
                    ActivityDescription item = new ActivityDescription(
                            am.getTaskThumbnail(recentInfo.persistentId),
                            icon, title, recentInfo.description, intent, id,
                            index, info.packageName);
                    activityDescriptions.add(item);
                    ++index;
                } else {
                    if (DEBUG) Log.v(TAG, "SKIPPING item " + id);
                }
            }
        }
        return activityDescriptions;
    }

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

    private void updateShownCompatMode() {
        final ActivityManager am = (ActivityManager)
                mContext.getSystemService(Context.ACTIVITY_SERVICE);
        int mode = am.getFrontActivityScreenCompatMode();
        switch (mode) {
            case ActivityManager.COMPAT_MODE_DISABLED:
                mCompatMode.setVisibility(View.VISIBLE);
                mCompatMode.setChecked(true);
                break;
            case ActivityManager.COMPAT_MODE_ENABLED:
                mCompatMode.setVisibility(View.VISIBLE);
                mCompatMode.setChecked(false);
                break;
            default:
                mCompatMode.setVisibility(View.GONE);
                break;
        }
    }

    private void refreshApplicationList() {
        mActivityDescriptions = getRecentTasks();
        mListAdapter.notifyDataSetInvalidated();
        if (mActivityDescriptions.size() > 0) {
            mLastVisibleItem = mActivityDescriptions.size() - 1; // scroll to bottom after reloading
            updateUiElements(getResources().getConfiguration());
            updateShownCompatMode();
        } else {
            // Immediately hide this panel
            hide(false);
        }
    }

    private Bitmap compositeBitmap(Bitmap background, Bitmap thumbnail) {
        Bitmap outBitmap = background.copy(background.getConfig(), true);
        if (thumbnail != null) {
            Canvas canvas = new Canvas(outBitmap);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setFilterBitmap(true);
            paint.setAlpha(255);
            final int srcWidth = thumbnail.getWidth();
            final int srcHeight = thumbnail.getHeight();
            canvas.drawBitmap(thumbnail,
                    new Rect(0, 0, srcWidth-1, srcHeight-1),
                    new RectF(GLOW_PADDING,
                            GLOW_PADDING - 7.0f,
                            outBitmap.getWidth() - GLOW_PADDING + 3.0f,
                            outBitmap.getHeight() - GLOW_PADDING + 7.0f), paint);
        }
        return outBitmap;
    }

    private void updateUiElements(Configuration config) {
        final int items = mActivityDescriptions.size();

        mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
        mRecentsGlowView.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
    }

    private void hide(boolean animate) {
        if (!animate) {
            setVisibility(View.GONE);
        }
        mBar.animateCollapse();
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
        final ActivityManager am = (ActivityManager)
                getContext().getSystemService(Context.ACTIVITY_SERVICE);
        if (ad.id >= 0) {
            // This is an active task; it should just go to the foreground.
            am.moveTaskToFront(ad.id, ActivityManager.MOVE_TASK_WITH_HOME);
        } else {
            Intent intent = ad.intent;
            intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
                    | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
            if (DEBUG) Log.v(TAG, "Starting activity " + intent);
            getContext().startActivity(intent);
        }
        hide(true);
    }
}
