
package com.sobot.album.app.album;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.widget.CompoundButton;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.PopupMenu;
import androidx.core.content.ContextCompat;

import com.sobot.album.Action;
import com.sobot.album.AlbumFile;
import com.sobot.album.AlbumFolder;
import com.sobot.album.Filter;
import com.sobot.album.R;
import com.sobot.album.SobotAlbum;
import com.sobot.album.api.widget.Widget;
import com.sobot.album.app.Contract;
import com.sobot.album.app.album.data.MediaReadTask;
import com.sobot.album.app.album.data.MediaReader;
import com.sobot.album.app.album.data.PathConversion;
import com.sobot.album.app.album.data.PathConvertTask;
import com.sobot.album.app.album.data.ThumbnailBuildTask;
import com.sobot.album.impl.OnItemClickListener;
import com.sobot.album.mediascanner.MediaScanner;
import com.sobot.album.util.AlbumUtils;
import com.sobot.album.widget.LoadingDialog;
import com.sobot.utils.SobotLogUtils;
import com.sobot.widget.ui.base.SobotBaseActivity;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class AlbumActivity extends SobotBaseActivity implements
        Contract.AlbumPresenter,
        MediaReadTask.Callback,
        GalleryActivity.Callback,
        PathConvertTask.Callback,
        ThumbnailBuildTask.Callback {

    private static final int CODE_ACTIVITY_NULL = 1;
    private static final int CODE_PERMISSION_STORAGE = 1;

    public static Filter<Long> sSizeFilter;
    public static Filter<String> sMimeFilter;
    public static Filter<Long> sDurationFilter;

    public static Action<ArrayList<AlbumFile>> sResult;
    public static Action<String> sCancel;

    private List<AlbumFolder> mAlbumFolders;
    private int mCurrentFolder;

    private Widget mWidget;
    private int mFunction;
    private int mChoiceMode;
    private int mColumnCount=15;
    private boolean mHasCamera;
    private int mLimitCount;

    private int mQuality;
    private long mLimitDuration;
    private long mLimitBytes;

    private boolean mFilterVisibility;

    private ArrayList<AlbumFile> mCheckedList;
    private MediaScanner mMediaScanner;

    private Contract.AlbumView mView;
    private FolderDialog mFolderDialog;
    private PopupMenu mCameraPopupMenu;
    private LoadingDialog mLoadingDialog;

    private MediaReadTask mMediaReadTask;
    private String limitText="";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        changeAppLanguage();

        initializeArgument();
        limitText=getResources().getQuantityString(R.plurals.album_check_image_limit, mLimitCount, mLimitCount);
        super.onCreate(savedInstanceState);

    }

    @Override
    protected int getContentViewResId() {
        return R.layout.sobot_album_activity_album;
    }

    @Override
    protected void initView() throws InterruptedException {
        setTitle(R.string.sobot_album_select_images);
        getLeftMenu().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                callbackCancel();
            }
        });
        mView = new AlbumView(this, this);
        mView.setupViews(mWidget, mColumnCount, mHasCamera, mChoiceMode);
        mView.setTitle(mWidget.getTitle());
        mView.setCompleteDisplay(false);
        mView.setLoadingDisplay(true);
    }

    @Override
    protected void initData() {
        /*this.permissionListener = new SobotPermissionListenerImpl() {
            public void onPermissionSuccessListener() {
                ArrayList<AlbumFile> checkedList = getIntent().getParcelableArrayListExtra(Album.KEY_INPUT_CHECKED_LIST);
                MediaReader mediaReader = new MediaReader(AlbumActivity.this, sSizeFilter, sMimeFilter, sDurationFilter, mFilterVisibility);
                mMediaReadTask = new MediaReadTask(mFunction, checkedList, mediaReader, AlbumActivity.this);
                mMediaReadTask.execute();
            }
        };
        if (!this.checkIsShowPermissionPop(this.getString(R.string.sobot_memory_card), this.getString(R.string.sobot_memory_card_yongtu), 1, 4)) {
            if (this.checkStoragePermission(4)) {
                ArrayList<AlbumFile> checkedList = getIntent().getParcelableArrayListExtra(Album.KEY_INPUT_CHECKED_LIST);
                MediaReader mediaReader = new MediaReader(this, sSizeFilter, sMimeFilter, sDurationFilter, mFilterVisibility);
                mMediaReadTask = new MediaReadTask(mFunction, checkedList, mediaReader, this);
                mMediaReadTask.execute();
            }
        }*/
        ArrayList<AlbumFile> checkedList = getIntent().getParcelableArrayListExtra(SobotAlbum.KEY_INPUT_CHECKED_LIST);
        MediaReader mediaReader = new MediaReader(AlbumActivity.this, sSizeFilter, sMimeFilter, sDurationFilter, mFilterVisibility);
        mMediaReadTask = new MediaReadTask(mFunction, checkedList, mediaReader, AlbumActivity.this);
        mMediaReadTask.execute();
    }

    private void initializeArgument() {
        Bundle argument = getIntent().getExtras();
        assert argument != null;
        mWidget = argument.getParcelable(SobotAlbum.KEY_INPUT_WIDGET);
        mFunction = argument.getInt(SobotAlbum.KEY_INPUT_FUNCTION);
        mChoiceMode = argument.getInt(SobotAlbum.KEY_INPUT_CHOICE_MODE);
        mColumnCount = argument.getInt(SobotAlbum.KEY_INPUT_COLUMN_COUNT);
        mHasCamera = argument.getBoolean(SobotAlbum.KEY_INPUT_ALLOW_CAMERA);
        mLimitCount = argument.getInt(SobotAlbum.KEY_INPUT_LIMIT_COUNT);
        mQuality = argument.getInt(SobotAlbum.KEY_INPUT_CAMERA_QUALITY);
        mLimitDuration = argument.getLong(SobotAlbum.KEY_INPUT_CAMERA_DURATION);
        mLimitBytes = argument.getLong(SobotAlbum.KEY_INPUT_CAMERA_BYTES);
        mFilterVisibility = argument.getBoolean(SobotAlbum.KEY_INPUT_FILTER_VISIBILITY);
    }

    /**
     * Use different layouts depending on the style.
     *
     * @return layout id.
     */

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mView.onConfigurationChanged(newConfig);
        if (mFolderDialog != null && !mFolderDialog.isShowing()) mFolderDialog = null;
    }



    @Override
    public void onScanCallback(ArrayList<AlbumFolder> albumFolders, ArrayList<AlbumFile> checkedFiles) {
        mMediaReadTask = null;
        switch (mChoiceMode) {
            case SobotAlbum.MODE_MULTIPLE: {
                mView.setCompleteDisplay(true);
                break;
            }
            case SobotAlbum.MODE_SINGLE: {
                mView.setCompleteDisplay(false);
                break;
            }
            default: {
                throw new AssertionError("This should not be the case.");
            }
        }

        mView.setLoadingDisplay(false);
        mAlbumFolders = albumFolders;
        mCheckedList = checkedFiles;

        if (mAlbumFolders.get(0).getAlbumFiles().isEmpty()) {
            Intent intent = new Intent(this, NullActivity.class);
            intent.putExtras(getIntent());
            startActivityForResult(intent, CODE_ACTIVITY_NULL);
        } else {
            showFolderAlbumFiles(0);
            int count = mCheckedList.size();
            mView.setCheckedCount(count);
            mView.setSubTitle(count + "/" + mLimitCount);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case CODE_ACTIVITY_NULL: {
                if (resultCode == RESULT_OK) {
                    String imagePath = NullActivity.parsePath(data);
                    String mimeType = AlbumUtils.getMimeType(imagePath);
                    if (!TextUtils.isEmpty(mimeType)) mCameraAction.onAction(imagePath);
                } else {
                    callbackCancel();
                }
                break;
            }
        }
    }

    @Override
    public void clickFolderSwitch() {
        if (mFolderDialog == null) {
            mFolderDialog = new FolderDialog(this, mWidget, mAlbumFolders, new OnItemClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    mCurrentFolder = position;
                    showFolderAlbumFiles(mCurrentFolder);
                }
            });
        }
        if (!mFolderDialog.isShowing()) mFolderDialog.show();
    }

    /**
     * Update data source.
     */
    private void showFolderAlbumFiles(int position) {
        this.mCurrentFolder = position;
        AlbumFolder albumFolder = mAlbumFolders.get(position);
        mView.bindAlbumFolder(albumFolder);
    }

    @Override
    public void clickCamera(View v) {
        int hasCheckSize = mCheckedList.size();
        if (hasCheckSize >= mLimitCount) {
            int messageRes;
            switch (mFunction) {
                case SobotAlbum.FUNCTION_CHOICE_IMAGE: {
                    messageRes = R.plurals.album_check_image_limit_camera;
                    break;
                }
                case SobotAlbum.FUNCTION_CHOICE_VIDEO: {
                    messageRes = R.plurals.album_check_video_limit_camera;
                    break;
                }
                case SobotAlbum.FUNCTION_CHOICE_ALBUM: {
                    messageRes = R.plurals.album_check_album_limit_camera;
                    break;
                }
                default: {
                    throw new AssertionError("This should not be the case.");
                }
            }
            mView.toast(getResources().getQuantityString(messageRes, mLimitCount, mLimitCount));
        } else {
            switch (mFunction) {
                case SobotAlbum.FUNCTION_CHOICE_IMAGE: {
                    takePicture();
                    break;
                }
                case SobotAlbum.FUNCTION_CHOICE_VIDEO: {
                    takeVideo();
                    break;
                }
                case SobotAlbum.FUNCTION_CHOICE_ALBUM: {
                    if (mCameraPopupMenu == null) {
                        mCameraPopupMenu = new PopupMenu(this, v);
//                        mCameraPopupMenu.getMenuInflater().inflate(R.menu.album_menu_item_camera, mCameraPopupMenu.getMenu());
//                        mCameraPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
//                            @Override
//                            public boolean onMenuItemClick(MenuItem item) {
//                                int id = item.getItemId();
//                                if (id == R.id.album_menu_camera_image) {
//                                    takePicture();
//                                } else if (id == R.id.album_menu_camera_video) {
//                                    takeVideo();
//                                }
//                                return true;
//                            }
//                        });
                    }
                    mCameraPopupMenu.show();
                    break;
                }
                default: {
                    throw new AssertionError("This should not be the case.");
                }
            }
        }
    }

    private void takePicture() {
        String filePath;
        if (mCurrentFolder == 0) {
            filePath = AlbumUtils.randomJPGPath();
        } else {
            File file = new File(mAlbumFolders.get(mCurrentFolder).getAlbumFiles().get(0).getPath());
            filePath = AlbumUtils.randomJPGPath(file.getParentFile());
        }
        SobotAlbum.camera(this)
                .image()
                .filePath(filePath)
                .onResult(mCameraAction)
                .start();
    }

    private void takeVideo() {
        String filePath;
        if (mCurrentFolder == 0) {
            filePath = AlbumUtils.randomMP4Path();
        } else {
            File file = new File(mAlbumFolders.get(mCurrentFolder).getAlbumFiles().get(0).getPath());
            filePath = AlbumUtils.randomMP4Path(file.getParentFile());
        }
        SobotAlbum.camera(this)
                .video()
                .filePath(filePath)
                .quality(mQuality)
                .limitDuration(mLimitDuration)
                .limitBytes(mLimitBytes)
                .onResult(mCameraAction)
                .start();
    }

    private Action<String> mCameraAction = new Action<String>() {
        @Override
        public void onAction(@NonNull String result) {
            if (mMediaScanner == null) {
                mMediaScanner = new MediaScanner(AlbumActivity.this);
            }
            mMediaScanner.scan(result);

            PathConversion conversion = new PathConversion(sSizeFilter, sMimeFilter, sDurationFilter);
            PathConvertTask task = new PathConvertTask(conversion, AlbumActivity.this);
            task.execute(result);
        }
    };

    @Override
    public void onConvertStart() {
        showLoadingDialog();
        mLoadingDialog.setMessage(R.string.album_converting);
    }

    @Override
    public void onConvertCallback(AlbumFile albumFile) {
        albumFile.setChecked(!albumFile.isDisable());
        if (albumFile.isDisable()) {
            if (mFilterVisibility) addFileToList(albumFile);
            else mView.toast(getString(R.string.album_take_file_unavailable));
        } else {
            addFileToList(albumFile);
        }

        dismissLoadingDialog();
    }

    private void addFileToList(AlbumFile albumFile) {
        if (mCurrentFolder != 0) {
            List<AlbumFile> albumFiles = mAlbumFolders.get(0).getAlbumFiles();
            if (albumFiles.size() > 0) albumFiles.add(0, albumFile);
            else albumFiles.add(albumFile);
        }

        AlbumFolder albumFolder = mAlbumFolders.get(mCurrentFolder);
        List<AlbumFile> albumFiles = albumFolder.getAlbumFiles();
        if (albumFiles.isEmpty()) {
            albumFiles.add(albumFile);
            mView.bindAlbumFolder(albumFolder);
        } else {
            albumFiles.add(0, albumFile);
            mView.notifyInsertItem(mHasCamera ? 1 : 0);
        }

        mCheckedList.add(albumFile);
        int count = mCheckedList.size();
        mView.setCheckedCount(count);
        mView.setSubTitle(count + "/" + mLimitCount);

        switch (mChoiceMode) {
            case SobotAlbum.MODE_SINGLE: {
                callbackResult();
                break;
            }
            case SobotAlbum.MODE_MULTIPLE: {
                // Nothing.
                break;
            }
            default: {
                throw new AssertionError("This should not be the case.");
            }
        }
    }

    @Override
    public void tryCheckItem(CompoundButton button, int position) {
        AlbumFile albumFile = mAlbumFolders.get(mCurrentFolder).getAlbumFiles().get(position);
        if (button.isChecked()) {
            if (mCheckedList.size() >= mLimitCount) {
                int messageRes;
                switch (mFunction) {
                    case SobotAlbum.FUNCTION_CHOICE_IMAGE: {
                        messageRes = R.plurals.album_check_image_limit;
                        break;
                    }
                    case SobotAlbum.FUNCTION_CHOICE_VIDEO: {
                        messageRes = R.plurals.album_check_video_limit;
                        break;
                    }
                    case SobotAlbum.FUNCTION_CHOICE_ALBUM: {
                        messageRes = R.plurals.album_check_album_limit;
                        break;
                    }
                    default: {
                        throw new AssertionError("This should not be the case.");
                    }
                }
                mView.toast(limitText);
                button.setChecked(false);
            } else {
                albumFile.setChecked(true);
                mCheckedList.add(albumFile);
                setCheckedCount();
            }
        } else {
            albumFile.setChecked(false);
            mCheckedList.remove(albumFile);
            setCheckedCount();
        }
    }

    private void setCheckedCount() {
        int count = mCheckedList.size();
        mView.setCheckedCount(count);
        mView.setSubTitle(count + "/" + mLimitCount);
    }

    @Override
    public void tryPreviewItem(int position) {
        switch (mChoiceMode) {
            case SobotAlbum.MODE_SINGLE: {
                AlbumFile albumFile = mAlbumFolders.get(mCurrentFolder).getAlbumFiles().get(position);
//                albumFile.setChecked(true);
//                mView.notifyItem(position);
                mCheckedList.add(albumFile);
                setCheckedCount();

                callbackResult();
                break;
            }
            case SobotAlbum.MODE_MULTIPLE: {
                GalleryActivity.sAlbumFiles = mAlbumFolders.get(mCurrentFolder).getAlbumFiles();
                SobotLogUtils.d("======全相册===="+mAlbumFolders.get(mCurrentFolder).getAlbumFiles().size());
                GalleryActivity.sCheckedCount = mCheckedList.size();
                GalleryActivity.sCurrentPosition = position;
                GalleryActivity.sCallback = this;
                GalleryActivity.previewMySelect = false;
                //预览全相册
                Intent intent = new Intent(this, GalleryActivity.class);
                intent.putExtras(getIntent());
                startActivity(intent);
                break;
            }
            default: {
                throw new AssertionError("This should not be the case.");
            }
        }
    }

    @Override
    public void tryPreviewChecked() {
        if (mCheckedList.size() > 0) {
            //预览已选中的
            GalleryActivity.sAlbumFiles = new ArrayList<>(mCheckedList);
            GalleryActivity.sCheckedCount = mCheckedList.size();
            GalleryActivity.sCurrentPosition = 0;
            GalleryActivity.sCallback = this;
            GalleryActivity.previewMySelect = true;
            Intent intent = new Intent(this, GalleryActivity.class);
            intent.putExtras(getIntent());
            startActivity(intent);
        }
    }

    @Override
    public void onPreviewComplete() {
        callbackResult();
    }

    @Override
    public void onPreviewChanged(AlbumFile albumFile) {
        ArrayList<AlbumFile> albumFiles = mAlbumFolders.get(mCurrentFolder).getAlbumFiles();
        int position = albumFiles.indexOf(albumFile);
        int notifyPosition = mHasCamera ? position + 1 : position;
        mView.notifyItem(notifyPosition);

        if (albumFile.isChecked()) {
            if (!mCheckedList.contains(albumFile)) mCheckedList.add(albumFile);
        } else {
            if (mCheckedList.contains(albumFile)) mCheckedList.remove(albumFile);
        }
        setCheckedCount();
    }

    @Override
    public void complete() {
        if (mCheckedList.isEmpty()) {
            int messageRes;
            switch (mFunction) {
                case SobotAlbum.FUNCTION_CHOICE_IMAGE: {
                    messageRes = R.string.album_check_image_little;
                    break;
                }
                case SobotAlbum.FUNCTION_CHOICE_VIDEO: {
                    messageRes = R.string.album_check_video_little;
                    break;
                }
                case SobotAlbum.FUNCTION_CHOICE_ALBUM: {
                    messageRes = R.string.album_check_album_little;
                    break;
                }
                default: {
                    throw new AssertionError("This should not be the case.");
                }
            }
            mView.toast(messageRes);
        } else {
            callbackResult();
        }
    }

    @Override
    public void onBackPressed() {
        if (mMediaReadTask != null) mMediaReadTask.cancel(true);
        callbackCancel();
    }

    /**
     * Callback result action.
     */
    private void callbackResult() {
        ThumbnailBuildTask task = new ThumbnailBuildTask(this, mCheckedList, this);
        task.execute();
    }

    @Override
    public void onThumbnailStart() {
        showLoadingDialog();
        mLoadingDialog.setMessage(R.string.album_thumbnail);
    }

    @Override
    public void onThumbnailCallback(ArrayList<AlbumFile> albumFiles) {
        if (sResult != null) sResult.onAction(albumFiles);
        dismissLoadingDialog();
        finish();
    }

    /**
     * Callback cancel action.
     */
    private void callbackCancel() {
        if (sCancel != null) sCancel.onAction("User canceled.");
        finish();
    }

    /**
     * Display loading dialog.
     */
    private void showLoadingDialog() {
        if (mLoadingDialog == null) {
            mLoadingDialog = new LoadingDialog(this);
            mLoadingDialog.setupViews(mWidget);
        }
        if (!mLoadingDialog.isShowing()) {
//            mLoadingDialog.show();
        }
    }

    /**
     * Dismiss loading dialog.
     */
    public void dismissLoadingDialog() {
        if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
            mLoadingDialog.dismiss();
        }
    }

    @Override
    public void finish() {
        sSizeFilter = null;
        sMimeFilter = null;
        sDurationFilter = null;
        sResult = null;
        sCancel = null;
        super.finish();
    }

    @Override
    public void bye() {

    }
}