/*
 * Copyright (C) 2015 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.recents.history;

import android.app.ActivityOptions;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateFormat;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
import com.android.systemui.recents.events.activity.HideHistoryEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;


/**
 * An adapter for the list of recent tasks in the history view.
 */
public class RecentsHistoryAdapter extends RecyclerView.Adapter<RecentsHistoryAdapter.ViewHolder> {

    private static final String TAG = "RecentsHistoryView";
    private static final boolean DEBUG = false;

    static final int DATE_ROW_VIEW_TYPE = 0;
    static final int TASK_ROW_VIEW_TYPE = 1;

    /**
     * View holder implementation. The {@param TaskCallbacks} are only called for TaskRow view
     * holders.
     */
    public static class ViewHolder extends RecyclerView.ViewHolder implements Task.TaskCallbacks {
        public final View content;

        public ViewHolder(View v) {
            super(v);
            content = v;
        }

        @Override
        public void onTaskDataLoaded(Task task) {
            // This callback is only made for TaskRow view holders
            ImageView iv = (ImageView) content.findViewById(R.id.icon);
            iv.setImageDrawable(task.icon);
        }

        @Override
        public void onTaskDataUnloaded() {
            // This callback is only made for TaskRow view holders
            ImageView iv = (ImageView) content.findViewById(R.id.icon);
            iv.setImageBitmap(null);
        }

        @Override
        public void onTaskStackIdChanged() {
            // Do nothing, this callback is only made for TaskRow view holders
        }
    }

    /**
     * A single row of content.
     */
    interface Row {
        int getViewType();
    }

    /**
     * A date row.
     */
    static class DateRow implements Row {

        public final String date;

        public DateRow(String date) {
            this.date = date;
        }

        @Override
        public int getViewType() {
            return RecentsHistoryAdapter.DATE_ROW_VIEW_TYPE;
        }
    }

    /**
     * A task row.
     */
    static class TaskRow implements Row, View.OnClickListener {

        public final Task task;
        public final int dateKey;

        public TaskRow(Task task, int dateKey) {
            this.task = task;
            this.dateKey = dateKey;
        }

        @Override
        public void onClick(View v) {
            SystemServicesProxy ssp = Recents.getSystemServices();
            ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
                    ActivityOptions.makeBasic());

            MetricsLogger.action(v.getContext(), MetricsLogger.ACTION_OVERVIEW_SELECT,
                    task.key.getComponent().toString());
        }

        @Override
        public int getViewType() {
            return RecentsHistoryAdapter.TASK_ROW_VIEW_TYPE;
        }
    }

    private Context mContext;
    private LayoutInflater mLayoutInflater;
    private final List<Task> mTasks = new ArrayList<>();
    private final List<Row> mRows = new ArrayList<>();
    private final SparseIntArray mTaskRowCount = new SparseIntArray();
    private TaskStack mStack;

    public RecentsHistoryAdapter(Context context) {
        mLayoutInflater = LayoutInflater.from(context);
    }

    /**
     * Updates this adapter with the given tasks.
     */
    public void updateTasks(Context context, TaskStack stack) {
        mContext = context;
        mStack = stack;

        final Locale l = context.getResources().getConfiguration().locale;
        final String dateFormatStr = DateFormat.getBestDateTimePattern(l, "EEEEMMMMd");
        final List<Task> tasksMostRecent = new ArrayList<>(stack.getHistoricalTasks());
        Collections.reverse(tasksMostRecent);
        int prevDateKey = -1;
        mRows.clear();
        mTaskRowCount.clear();
        for (Task task : tasksMostRecent) {
            if (task.isFreeformTask()) {
                continue;
            }

            Calendar cal = Calendar.getInstance(l);
            cal.setTimeInMillis(task.key.lastActiveTime);
            int dateKey = Objects.hash(cal.get(Calendar.YEAR), cal.get(Calendar.DAY_OF_YEAR));
            if (dateKey != prevDateKey) {
                prevDateKey = dateKey;
                mRows.add(new DateRow(DateFormat.format(dateFormatStr, cal).toString()));
            }
            mRows.add(new TaskRow(task, dateKey));
            mTaskRowCount.put(dateKey, mTaskRowCount.get(dateKey, 0) + 1);
        }
        notifyDataSetChanged();
    }

    /**
     * Removes historical tasks belonging to the specified package and user. We do not need to
     * remove the task from the TaskStack since the TaskStackView will also receive this event.
     */
    public void removeTasks(String packageName, int userId) {
        for (int i = mRows.size() - 1; i >= 0; i--) {
            Row row = mRows.get(i);
            if (row.getViewType() == TASK_ROW_VIEW_TYPE) {
                TaskRow taskRow = (TaskRow) row;
                Task task = taskRow.task;
                String taskPackage = task.key.getComponent().getPackageName();
                if (task.key.userId == userId && taskPackage.equals(packageName)) {
                    i = removeTaskRow(i);
                }
            }
        }
        if (mRows.isEmpty()) {
            dismissHistory();
        }
    }

    /**
     * Returns the row at the given {@param position}.
     */
    public Row getRow(int position) {
        return mRows.get(position);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case DATE_ROW_VIEW_TYPE:
                return new ViewHolder(mLayoutInflater.inflate(R.layout.recents_history_date, parent,
                        false));
            case TASK_ROW_VIEW_TYPE:
                return new ViewHolder(mLayoutInflater.inflate(R.layout.recents_history_task, parent,
                        false));
            default:
                return new ViewHolder(null);
        }
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        RecentsTaskLoader loader = Recents.getTaskLoader();

        Row row = mRows.get(position);
        int viewType = row.getViewType();
        switch (viewType) {
            case DATE_ROW_VIEW_TYPE: {
                TextView tv = (TextView) holder.content;
                tv.setText(((DateRow) row).date);
                break;
            }
            case TASK_ROW_VIEW_TYPE: {
                TaskRow taskRow = (TaskRow) row;
                taskRow.task.addCallback(holder);
                TextView tv = (TextView) holder.content.findViewById(R.id.description);
                tv.setText(taskRow.task.title);
                holder.content.setOnClickListener(taskRow);
                loader.loadTaskData(taskRow.task);
                break;
            }
        }
    }

    @Override
    public void onViewRecycled(ViewHolder holder) {
        RecentsTaskLoader loader = Recents.getTaskLoader();

        int position = holder.getAdapterPosition();
        if (position != RecyclerView.NO_POSITION) {
            Row row = mRows.get(position);
            int viewType = row.getViewType();
            if (viewType == TASK_ROW_VIEW_TYPE) {
                TaskRow taskRow = (TaskRow) row;
                taskRow.task.removeCallback(holder);
                loader.unloadTaskData(taskRow.task);
            }
        }
    }

    public void onTaskRemoved(Task task, int position) {
        // Since this is removed from the history, we need to update the stack as well to ensure
        // that the model is correct
        mStack.removeTask(task);
        removeTaskRow(position);
        if (mRows.isEmpty()) {
            dismissHistory();
        }
    }

    @Override
    public int getItemCount() {
        return mRows.size();
    }

    @Override
    public int getItemViewType(int position) {
        return mRows.get(position).getViewType();
    }

    /**
     * Removes a task row, also removing the associated {@link DateRow} if there are no more tasks
     * in that date group.
     *
     * @param position an adapter position of a task row such that 0 < position < num rows.
     * @return the index of the last removed row
     */
    private int removeTaskRow(int position) {
        // Remove the task at that row
        TaskRow taskRow = (TaskRow) mRows.remove(position);
        int numTasks = mTaskRowCount.get(taskRow.dateKey) - 1;
        mTaskRowCount.put(taskRow.dateKey, numTasks);
        notifyItemRemoved(position);

        if (numTasks == 0) {
            // If that was the last task row in the group, then remove the date as well
            mRows.remove(position - 1);
            mTaskRowCount.removeAt(mTaskRowCount.indexOfKey(taskRow.dateKey));
            notifyItemRemoved(position - 1);
            return position - 1;
        } else {
            return position;
        }
    }

    /**
     * Dismisses history back to the stack view.
     */
    private void dismissHistory() {
        EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
        EventBus.getDefault().send(new HideHistoryButtonEvent());
    }
}
