/*
 * 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.messaging.ui.mediapicker;

import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import androidx.appcompat.app.ActionBar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import com.android.messaging.Factory;
import com.android.messaging.R;
import com.android.messaging.datamodel.data.GalleryGridItemData;
import com.android.messaging.datamodel.data.MediaPickerData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.MediaPickerData.MediaPickerDataListener;
import com.android.messaging.util.Assert;
import com.android.messaging.util.OsUtil;

/**
 * Chooser which allows the user to select one or more existing images or videos or audios.
 */
class GalleryMediaChooser extends MediaChooser implements
        GalleryGridView.GalleryGridViewListener, MediaPickerDataListener {
    private final GalleryGridAdapter mAdapter;
    private GalleryGridView mGalleryGridView;
    private View mMissingPermissionView;

    GalleryMediaChooser(final MediaPicker mediaPicker) {
        super(mediaPicker);
        mAdapter = new GalleryGridAdapter(Factory.get().getApplicationContext(), null);
    }

    @Override
    public int getSupportedMediaTypes() {
        return (MediaPicker.MEDIA_TYPE_IMAGE
                | MediaPicker.MEDIA_TYPE_VIDEO
                | MediaPicker.MEDIA_TYPE_AUDIO);
    }

    @Override
    public View destroyView() {
        mGalleryGridView.setAdapter(null);
        mAdapter.setHostInterface(null);
        // The loader is started only if startMediaPickerDataLoader() is called
        if (OsUtil.hasStoragePermission()) {
            mBindingRef.getData().destroyLoader(MediaPickerData.GALLERY_MEDIA_LOADER);
        }
        return super.destroyView();
    }

    @Override
    public int getIconResource() {
        return R.drawable.ic_image_light;
    }

    @Override
    public int getIconDescriptionResource() {
        return R.string.mediapicker_galleryChooserDescription;
    }

    @Override
    public boolean canSwipeDown() {
        return mGalleryGridView.canSwipeDown();
    }

    @Override
    public void onItemSelected(final MessagePartData item) {
        mMediaPicker.dispatchItemsSelected(item, !mGalleryGridView.isMultiSelectEnabled());
    }

    @Override
    public void onItemUnselected(final MessagePartData item) {
        mMediaPicker.dispatchItemUnselected(item);
    }

    @Override
    public void onConfirmSelection() {
        // The user may only confirm if multiselect is enabled.
        Assert.isTrue(mGalleryGridView.isMultiSelectEnabled());
        mMediaPicker.dispatchConfirmItemSelection();
    }

    @Override
    public void onUpdate() {
        mMediaPicker.invalidateOptionsMenu();
    }

    @Override
    public void onCreateOptionsMenu(final MenuInflater inflater, final Menu menu) {
        if (mView != null) {
            mGalleryGridView.onCreateOptionsMenu(inflater, menu);
        }
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        return (mView != null) ? mGalleryGridView.onOptionsItemSelected(item) : false;
    }

    @Override
    protected View createView(final ViewGroup container) {
        final LayoutInflater inflater = getLayoutInflater();
        final View view = inflater.inflate(
                R.layout.mediapicker_gallery_chooser,
                container /* root */,
                false /* attachToRoot */);

        mGalleryGridView = (GalleryGridView) view.findViewById(R.id.gallery_grid_view);
        mAdapter.setHostInterface(mGalleryGridView);
        mGalleryGridView.setAdapter(mAdapter);
        mGalleryGridView.setHostInterface(this);
        mGalleryGridView.setDraftMessageDataModel(mMediaPicker.getDraftMessageDataModel());
        if (OsUtil.hasStoragePermission()) {
            startMediaPickerDataLoader();
        }

        mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
        updateForPermissionState(OsUtil.hasStoragePermission());
        return view;
    }

    @Override
    int getActionBarTitleResId() {
        return R.string.mediapicker_gallery_title;
    }

    @Override
    public void onDocumentPickerItemClicked() {
        mMediaPicker.launchDocumentPicker();
    }

    @Override
    void updateActionBar(final ActionBar actionBar) {
        super.updateActionBar(actionBar);
        if (mGalleryGridView == null) {
            return;
        }
        final int selectionCount = mGalleryGridView.getSelectionCount();
        if (selectionCount > 0 && mGalleryGridView.isMultiSelectEnabled()) {
            actionBar.setTitle(getContext().getResources().getString(
                    R.string.mediapicker_gallery_title_selection,
                    selectionCount));
        }
    }

    @Override
    public void onMediaPickerDataUpdated(final MediaPickerData mediaPickerData, final Object data,
            final int loaderId) {
        mBindingRef.ensureBound(mediaPickerData);
        Assert.equals(MediaPickerData.GALLERY_MEDIA_LOADER, loaderId);
        Cursor rawCursor = null;
        if (data instanceof Cursor) {
            rawCursor = (Cursor) data;
        }
        // Before delivering the cursor, wrap around the local gallery cursor
        // with an extra item for document picker integration in the front.
        final MatrixCursor specialItemsCursor =
                new MatrixCursor(GalleryGridItemData.SPECIAL_ITEM_COLUMNS);
        specialItemsCursor.addRow(new Object[] { GalleryGridItemData.ID_DOCUMENT_PICKER_ITEM });
        final MergeCursor cursor =
                new MergeCursor(new Cursor[] { specialItemsCursor, rawCursor });
        mAdapter.swapCursor(cursor);
    }

    @Override
    public void onResume() {
        if (OsUtil.hasStoragePermission()) {
            // Work around a bug in MediaStore where cursors querying the Files provider don't get
            // updated for changes to Images.Media or Video.Media.
            startMediaPickerDataLoader();
        }
    }

    @Override
    protected void setSelected(final boolean selected) {
        super.setSelected(selected);
        if (selected && !OsUtil.hasStoragePermission()) {
            mMediaPicker.requestPermissions(
                    new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
                    MediaPicker.GALLERY_PERMISSION_REQUEST_CODE);
        }
    }

    private void startMediaPickerDataLoader() {
        mBindingRef
                .getData()
                .startLoader(MediaPickerData.GALLERY_MEDIA_LOADER, mBindingRef, null, this);
    }

    @Override
    protected void onRequestPermissionsResult(
            final int requestCode, final String permissions[], final int[] grantResults) {
        if (requestCode == MediaPicker.GALLERY_PERMISSION_REQUEST_CODE) {
            final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
            if (permissionGranted) {
                startMediaPickerDataLoader();
            }
            updateForPermissionState(permissionGranted);
        }
    }

    private void updateForPermissionState(final boolean granted) {
        // onRequestPermissionsResult can sometimes get called before createView().
        if (mGalleryGridView == null) {
            return;
        }

        mGalleryGridView.setVisibility(granted ? View.VISIBLE : View.GONE);
        mMissingPermissionView.setVisibility(granted ? View.GONE : View.VISIBLE);
    }
}
