/*
 * Copyright (C) 2016 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.documentsui.sorting;

import android.annotation.StringRes;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;

import com.android.documentsui.R;
import com.android.documentsui.sorting.SortController.WidgetController;
import com.android.documentsui.sorting.SortDimension.SortDirection;
import com.android.documentsui.sorting.SortModel.SortDimensionId;
import com.android.documentsui.sorting.SortModel.UpdateType;

/**
 * View controller for the sort widget in grid mode and in small screens.
 */
public final class DropdownSortWidgetController implements WidgetController {

    private static final int LEVEL_UPWARD = 0;
    private static final int LEVEL_DOWNWARD = 10000;

    private final SortModel mModel;
    private final View mWidget;
    private final TextView mDimensionButton;
    private final PopupMenu mMenu;
    private final ImageView mArrow;

    public DropdownSortWidgetController(SortModel model, View widget) {
        mModel = model;
        mWidget = widget;

        mDimensionButton = (TextView) mWidget.findViewById(R.id.sort_dimen_dropdown);
        mDimensionButton.setOnClickListener(this::showMenu);

        mMenu = new PopupMenu(widget.getContext(), mDimensionButton, Gravity.END | Gravity.TOP);
        mMenu.setOnMenuItemClickListener(this::onSelectDimension);

        mArrow = (ImageView) mWidget.findViewById(R.id.sort_arrow);
        mArrow.setOnClickListener(this::onChangeDirection);

        populateMenuItems();
        onModelUpdate(mModel, SortModel.UPDATE_TYPE_UNSPECIFIED);

        mModel.addListener(this::onModelUpdate);
    }

    @Override
    public void setVisibility(int visibility) {
        mWidget.setVisibility(visibility);
    }

    private void populateMenuItems() {
        Menu menu = mMenu.getMenu();
        menu.clear();
        for (int i = 0; i < mModel.getSize(); ++i) {
            SortDimension dimension = mModel.getDimensionAt(i);
            if (dimension.getSortCapability() != SortDimension.SORT_CAPABILITY_NONE) {
                menu.add(0, dimension.getId(), Menu.NONE, dimension.getLabelId());
            }
        }
    }

    private void showMenu(View v) {
        mMenu.show();
    }

    private void onModelUpdate(SortModel model, @UpdateType int updateType) {
        final @SortDimensionId int sortedId = model.getSortedDimensionId();

        if ((updateType & SortModel.UPDATE_TYPE_VISIBILITY) != 0) {
            updateVisibility();
        }

        if ((updateType & SortModel.UPDATE_TYPE_SORTING) != 0) {
            bindSortedDimension(sortedId);
            bindSortDirection(sortedId);
        }
    }

    private void updateVisibility() {
        Menu menu = mMenu.getMenu();

        for (int i = 0; i < menu.size(); ++i) {
            MenuItem item = menu.getItem(i);
            SortDimension dimension = mModel.getDimensionById(item.getItemId());
            item.setVisible(dimension.getVisibility() == View.VISIBLE);
        }
    }

    private void bindSortedDimension(@SortDimensionId int sortedId) {
        if (sortedId == SortModel.SORT_DIMENSION_ID_UNKNOWN) {
            mDimensionButton.setText(R.string.not_sorted);
        } else {
            SortDimension dimension = mModel.getDimensionById(sortedId);
            mDimensionButton.setText(dimension.getLabelId());
        }
    }

    private void bindSortDirection(@SortDimensionId int sortedId) {
        if (sortedId == SortModel.SORT_DIMENSION_ID_UNKNOWN) {
            mArrow.setVisibility(View.INVISIBLE);
        } else {
            final SortDimension dimension = mModel.getDimensionById(sortedId);
            switch (dimension.getSortDirection()) {
                case SortDimension.SORT_DIRECTION_NONE:
                    mArrow.setVisibility(View.INVISIBLE);
                    break;
                case SortDimension.SORT_DIRECTION_ASCENDING:
                    showArrow(LEVEL_UPWARD, R.string.sort_direction_ascending);
                    break;
                case SortDimension.SORT_DIRECTION_DESCENDING:
                    showArrow(LEVEL_DOWNWARD, R.string.sort_direction_descending);
                    break;
                default:
                    throw new IllegalStateException(
                            "Unknown sort direction: " + dimension.getSortDirection() + ".");
            }
        }
    }

    private void showArrow(int level, @StringRes int descriptionId) {
        mArrow.setVisibility(View.VISIBLE);

        mArrow.getDrawable().mutate();
        mArrow.setImageLevel(level);
        mArrow.setContentDescription(mArrow.getContext().getString(descriptionId));
    }

    private boolean onSelectDimension(MenuItem item) {
        final @SortDirection int preferredDirection = mModel.getCurrentSortDirection();

        final SortDimension dimension = mModel.getDimensionById(item.getItemId());
        final @SortDirection int direction;
        if ((dimension.getSortCapability() & preferredDirection) > 0) {
            direction = preferredDirection;
        } else {
            direction = dimension.getDefaultSortDirection();
        }

        mModel.sortByUser(dimension.getId(), direction);

        return true;
    }

    private void onChangeDirection(View v) {
        final @SortDimensionId int id = mModel.getSortedDimensionId();
        assert(id != SortModel.SORT_DIMENSION_ID_UNKNOWN);

        final SortDimension dimension = mModel.getDimensionById(id);
        mModel.sortByUser(dimension.getId(), dimension.getNextDirection());
    }
}
