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

import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.MenuItem;
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.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
import com.android.settingslib.SuggestionParser;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;

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

public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.DashboardItemHolder>
        implements View.OnClickListener {
    public static final String TAG = "DashboardAdapter";
    private static final String STATE_SUGGESTION_LIST = "suggestion_list";
    private static final String STATE_CATEGORY_LIST = "category_list";
    private static final String STATE_IS_SHOWING_ALL = "is_showing_all";
    private static final String STATE_SUGGESTION_MODE = "suggestion_mode";
    private static final int NS_SPACER = 0;
    private static final int NS_SUGGESTION = 1000;
    private static final int NS_ITEMS = 2000;
    private static final int NS_CONDITION = 3000;

    private static int SUGGESTION_MODE_DEFAULT = 0;
    private static int SUGGESTION_MODE_COLLAPSED = 1;
    private static int SUGGESTION_MODE_EXPANDED = 2;

    private static final int DEFAULT_SUGGESTION_COUNT = 2;

    private final List<Object> mItems = new ArrayList<>();
    private final List<Integer> mTypes = new ArrayList<>();
    private final List<Integer> mIds = new ArrayList<>();
    private final IconCache mCache;

    private final Context mContext;

    private List<DashboardCategory> mCategories;
    private List<Condition> mConditions;
    private List<Tile> mSuggestions;

    private boolean mIsShowingAll;
    // Used for counting items;
    private int mId;

    private int mSuggestionMode = SUGGESTION_MODE_DEFAULT;

    private Condition mExpandedCondition = null;
    private SuggestionParser mSuggestionParser;

    public DashboardAdapter(Context context, SuggestionParser parser, Bundle savedInstanceState,
                List<Condition> conditions) {
        mContext = context;
        mCache = new IconCache(context);
        mSuggestionParser = parser;
        mConditions = conditions;

        setHasStableIds(true);

        boolean showAll = true;
        if (savedInstanceState != null) {
            mSuggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
            mCategories = savedInstanceState.getParcelableArrayList(STATE_CATEGORY_LIST);
            showAll = savedInstanceState.getBoolean(STATE_IS_SHOWING_ALL, true);
            mSuggestionMode = savedInstanceState.getInt(
                    STATE_SUGGESTION_MODE, SUGGESTION_MODE_DEFAULT);
        }
        setShowingAll(showAll);
    }

    public List<Tile> getSuggestions() {
        return mSuggestions;
    }

    public void setCategoriesAndSuggestions(List<DashboardCategory> categories,
            List<Tile> suggestions) {
        mSuggestions = suggestions;
        mCategories = categories;

        // TODO: Better place for tinting?
        TypedValue tintColor = new TypedValue();
        mContext.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent,
                tintColor, true);
        for (int i = 0; i < categories.size(); i++) {
            for (int j = 0; j < categories.get(i).tiles.size(); j++) {
                Tile tile = categories.get(i).tiles.get(j);

                if (!mContext.getPackageName().equals(
                        tile.intent.getComponent().getPackageName())) {
                    // If this drawable is coming from outside Settings, tint it to match the
                    // color.
                    tile.icon.setTint(tintColor.data);
                }
            }
        }
        recountItems();
    }

    public void setConditions(List<Condition> conditions) {
        mConditions = conditions;
        recountItems();
    }

    public boolean isShowingAll() {
        return mIsShowingAll;
    }

    public void notifyChanged(Tile tile) {
        notifyDataSetChanged();
    }

    public void setShowingAll(boolean showingAll) {
        mIsShowingAll = showingAll;
        recountItems();
    }

    private void recountItems() {
        reset();
        boolean hasConditions = false;
        for (int i = 0; mConditions != null && i < mConditions.size(); i++) {
            boolean shouldShow = mConditions.get(i).shouldShow();
            hasConditions |= shouldShow;
            countItem(mConditions.get(i), R.layout.condition_card, shouldShow, NS_CONDITION);
        }
        boolean hasSuggestions = mSuggestions != null && mSuggestions.size() != 0;
        countItem(null, R.layout.dashboard_spacer, hasConditions && hasSuggestions, NS_SPACER);
        countItem(null, R.layout.suggestion_header, hasSuggestions, NS_SPACER);
        resetCount();
        if (mSuggestions != null) {
            int maxSuggestions = getDisplayableSuggestionCount();
            for (int i = 0; i < mSuggestions.size(); i++) {
                countItem(mSuggestions.get(i), R.layout.suggestion_tile, i < maxSuggestions,
                        NS_SUGGESTION);
            }
        }
        resetCount();
        for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
            DashboardCategory category = mCategories.get(i);
            countItem(category, R.layout.dashboard_category, mIsShowingAll, NS_ITEMS);
            for (int j = 0; j < category.tiles.size(); j++) {
                Tile tile = category.tiles.get(j);
                countItem(tile, R.layout.dashboard_tile, mIsShowingAll
                        || ArrayUtils.contains(DashboardSummary.INITIAL_ITEMS,
                        tile.intent.getComponent().getClassName()), NS_ITEMS);
            }
        }
        notifyDataSetChanged();
    }

    private void resetCount() {
        mId = 0;
    }

    private void reset() {
        mItems.clear();
        mTypes.clear();
        mIds.clear();
        mId = 0;
    }

    private void countItem(Object object, int type, boolean add, int nameSpace) {
        if (add) {
            mItems.add(object);
            mTypes.add(type);
            // TODO: Counting namespaces for handling of suggestions/conds appearing/disappearing.
            mIds.add(mId + nameSpace);
        }
        mId++;
    }

    private int getDisplayableSuggestionCount() {
        final int suggestionSize = mSuggestions.size();
        return mSuggestionMode == SUGGESTION_MODE_DEFAULT
                ? Math.min(DEFAULT_SUGGESTION_COUNT, suggestionSize)
                : mSuggestionMode == SUGGESTION_MODE_EXPANDED
                        ? suggestionSize : 0;
    }

    @Override
    public DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new DashboardItemHolder(LayoutInflater.from(parent.getContext()).inflate(
                viewType, parent, false));
    }

    @Override
    public void onBindViewHolder(DashboardItemHolder holder, int position) {
        switch (mTypes.get(position)) {
            case R.layout.dashboard_category:
                onBindCategory(holder, (DashboardCategory) mItems.get(position));
                break;
            case R.layout.dashboard_tile:
                final Tile tile = (Tile) mItems.get(position);
                onBindTile(holder, tile);
                holder.itemView.setTag(tile);
                holder.itemView.setOnClickListener(this);
                break;
            case R.layout.suggestion_header:
                onBindSuggestionHeader(holder);
                break;
            case R.layout.suggestion_tile:
                final Tile suggestion = (Tile) mItems.get(position);
                onBindTile(holder, suggestion);
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        MetricsLogger.action(mContext, MetricsEvent.ACTION_SETTINGS_SUGGESTION,
                                DashboardAdapter.getSuggestionIdentifier(mContext, suggestion));
                        ((SettingsActivity) mContext).startSuggestion(suggestion.intent);
                    }
                });
                holder.itemView.findViewById(R.id.overflow).setOnClickListener(
                        new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                showRemoveOption(v, suggestion);
                            }
                        });
                break;
            case R.layout.see_all:
                onBindSeeAll(holder);
                break;
            case R.layout.condition_card:
                ConditionAdapterUtils.bindViews((Condition) mItems.get(position), holder,
                        mItems.get(position) == mExpandedCondition, this,
                        new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                onExpandClick(v);
                            }
                        });
                break;
        }
    }

    private void showRemoveOption(View v, final Tile suggestion) {
        PopupMenu popup = new PopupMenu(
                new ContextThemeWrapper(mContext, R.style.Theme_AppCompat_DayNight), v);
        popup.getMenu().add(R.string.suggestion_remove).setOnMenuItemClickListener(
                new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                MetricsLogger.action(mContext, MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION,
                        DashboardAdapter.getSuggestionIdentifier(mContext, suggestion));
                disableSuggestion(suggestion);
                mSuggestions.remove(suggestion);
                recountItems();
                return true;
            }
        });
        popup.show();
    }

    public void disableSuggestion(Tile suggestion) {
        if (mSuggestionParser == null) {
            return;
        }
        if (mSuggestionParser.dismissSuggestion(suggestion)) {
            mContext.getPackageManager().setComponentEnabledSetting(
                    suggestion.intent.getComponent(),
                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                    PackageManager.DONT_KILL_APP);
            mSuggestionParser.markCategoryDone(suggestion.category);
        }
    }

    private void onBindSuggestionHeader(final DashboardItemHolder holder) {
        final boolean moreSuggestions = hasMoreSuggestions();
        final int undisplayedSuggestionCount =
                mSuggestions.size() - getDisplayableSuggestionCount();
        holder.icon.setImageResource(moreSuggestions ? R.drawable.ic_expand_more
                : R.drawable.ic_expand_less);
        holder.title.setText(mContext.getString(R.string.suggestions_title, mSuggestions.size()));
        String summaryContentDescription;
        if (moreSuggestions) {
            summaryContentDescription = mContext.getResources().getQuantityString(
                    R.plurals.settings_suggestion_header_summary_hidden_items,
                    undisplayedSuggestionCount, undisplayedSuggestionCount);
        } else {
            summaryContentDescription = mContext.getString(R.string.condition_expand_hide);
        }
        holder.summary.setContentDescription(summaryContentDescription);

        if (undisplayedSuggestionCount == 0) {
            holder.summary.setText(null);
        } else {
            holder.summary.setText(
                    mContext.getString(R.string.suggestions_summary, undisplayedSuggestionCount));
        }
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (hasMoreSuggestions()) {
                    mSuggestionMode = SUGGESTION_MODE_EXPANDED;
                } else {
                    mSuggestionMode = SUGGESTION_MODE_COLLAPSED;
                }
                recountItems();
            }
        });
    }

    private boolean hasMoreSuggestions() {
        return mSuggestionMode == SUGGESTION_MODE_COLLAPSED
                || (mSuggestionMode == SUGGESTION_MODE_DEFAULT
                && mSuggestions.size() > DEFAULT_SUGGESTION_COUNT);
    }

    private void onBindTile(DashboardItemHolder holder, Tile tile) {
        holder.icon.setImageDrawable(mCache.getIcon(tile.icon));
        holder.title.setText(tile.title);
        if (!TextUtils.isEmpty(tile.summary)) {
            holder.summary.setText(tile.summary);
            holder.summary.setVisibility(View.VISIBLE);
        } else {
            holder.summary.setVisibility(View.GONE);
        }
    }

    private void onBindCategory(DashboardItemHolder holder, DashboardCategory category) {
        holder.title.setText(category.title);
    }

    private void onBindSeeAll(DashboardItemHolder holder) {
        holder.title.setText(mIsShowingAll ? R.string.see_less
                : R.string.see_all);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setShowingAll(!mIsShowingAll);
            }
        });
    }

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

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

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

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.dashboard_tile) {
            ((SettingsActivity) mContext).openTile((Tile) v.getTag());
            return;
        }
        if (v.getTag() == mExpandedCondition) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK,
                    mExpandedCondition.getMetricsConstant());
            mExpandedCondition.onPrimaryClick();
        } else {
            mExpandedCondition = (Condition) v.getTag();
            MetricsLogger.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
                    mExpandedCondition.getMetricsConstant());
            notifyDataSetChanged();
        }
    }

    public void onExpandClick(View v) {
        if (v.getTag() == mExpandedCondition) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_COLLAPSE,
                    mExpandedCondition.getMetricsConstant());
            mExpandedCondition = null;
        } else {
            mExpandedCondition = (Condition) v.getTag();
            MetricsLogger.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
                    mExpandedCondition.getMetricsConstant());
        }
        notifyDataSetChanged();
    }

    public Object getItem(long itemId) {
        for (int i = 0; i < mIds.size(); i++) {
            if (mIds.get(i) == itemId) {
                return mItems.get(i);
            }
        }
        return null;
    }

    public static String getSuggestionIdentifier(Context context, Tile suggestion) {
        String packageName = suggestion.intent.getComponent().getPackageName();
        if (packageName.equals(context.getPackageName())) {
            // Since Settings provides several suggestions, fill in the class instead of the
            // package for these.
            packageName = suggestion.intent.getComponent().getClassName();
        }
        return packageName;
    }

    void onSaveInstanceState(Bundle outState) {
        if (mSuggestions != null) {
            outState.putParcelableArrayList(STATE_SUGGESTION_LIST,
                    new ArrayList<Tile>(mSuggestions));
        }
        if (mCategories != null) {
            outState.putParcelableArrayList(STATE_CATEGORY_LIST,
                    new ArrayList<DashboardCategory>(mCategories));
        }
        outState.putBoolean(STATE_IS_SHOWING_ALL, mIsShowingAll);
        outState.putInt(STATE_SUGGESTION_MODE, mSuggestionMode);
    }

    private static class IconCache {

        private final Context mContext;
        private final ArrayMap<Icon, Drawable> mMap = new ArrayMap<>();

        public IconCache(Context context) {
            mContext = context;
        }

        public Drawable getIcon(Icon icon) {
            Drawable drawable = mMap.get(icon);
            if (drawable == null) {
                drawable = icon.loadDrawable(mContext);
                mMap.put(icon, drawable);
            }
            return drawable;
        }
    }

    public static class DashboardItemHolder extends RecyclerView.ViewHolder {
        public final ImageView icon;
        public final TextView title;
        public final TextView summary;

        public DashboardItemHolder(View itemView) {
            super(itemView);
            icon = (ImageView) itemView.findViewById(android.R.id.icon);
            title = (TextView) itemView.findViewById(android.R.id.title);
            summary = (TextView) itemView.findViewById(android.R.id.summary);
        }
    }
}
