package com.lemenzo.gallery.trash;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.lemenzo.gallery.R;
import com.lemenzo.gallery.gallery.GalleryAdapter;
import com.lemenzo.gallery.model.MediaItem;
import com.lemenzo.gallery.util.BackgroundExecutors;
import com.lemenzo.gallery.ui.MediaGridDecoration;
import com.lemenzo.gallery.ui.RecyclerTuning;
import com.lemenzo.gallery.ui.SystemInsets;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;

public final class TrashActivity extends Activity {
    private static final String TAG = "LemenzoGalleryTrash";
    private static final int REQUEST_RESTORE = 7101;
    private static final int REQUEST_DELETE = 7102;

    private final ExecutorService executor = BackgroundExecutors.single("LemenzoGalleryTrash");
    private TrashAdapter adapter;
    private View empty;
    private MediaItem pending;
    private static final int PAGE_SIZE = 180;
    private int loadedCount;
    private MediaItem pageAnchor;
    private boolean loadingPage;
    private boolean endReached;
    private java.util.concurrent.Future<?> pageTask;
    private int loadGeneration;
    private RecyclerView grid;

    @Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        setContentView(R.layout.activity_trash);
        SystemInsets.apply(this);
        findViewById(R.id.back_button).setOnClickListener(v -> finish());

        grid = findViewById(R.id.trash_grid);
        empty = findViewById(R.id.empty_state);
        int columns = 3;
        GridLayoutManager layoutManager = new GridLayoutManager(this, columns);
        adapter = new TrashAdapter(this, new GalleryAdapter.Listener() {
            @Override public void onOpen(MediaItem item) { showActions(item); }
            @Override public void onSelectionChanged(int count) {}
        });
        layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override public int getSpanSize(int position) {
                return adapter.spanSize(position, columns);
            }
        });
        grid.setLayoutManager(layoutManager);
        grid.addItemDecoration(new MediaGridDecoration(2, columns));
        grid.setAdapter(adapter);
        RecyclerTuning.applyMediaGrid(grid);
        grid.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (dy <= 0 || loadingPage || endReached) return;
                int last = layoutManager.findLastVisibleItemPosition();
                if (last >= Math.max(0, adapter.getItemCount() - 36)) loadNextPage(false);
            }
        });
        load();
    }

    private void load() {
        if (pageTask != null) { pageTask.cancel(true); pageTask = null; }
        loadedCount = 0; pageAnchor = null; loadingPage = false; endReached = false; loadGeneration++;
        if (adapter != null) adapter.submit(java.util.Collections.emptyList(), false);
        loadNextPage(true);
    }

    private void loadNextPage(boolean firstPage) {
        if (loadingPage || endReached) return;
        loadingPage = true; final MediaItem anchor = pageAnchor; final int generation = loadGeneration;
        pageTask = executor.submit(() -> {
            List<MediaItem> items = new TrashViewModel(this).pageAfter(anchor, PAGE_SIZE);
            runOnUiThread(() -> {
                if (generation != loadGeneration || isFinishing() || adapter == null) return;
                loadingPage = false;
                if (firstPage) adapter.submit(items, false); else adapter.append(items, false);
                loadedCount += items.size();
                if (!items.isEmpty()) pageAnchor = items.get(items.size() - 1);
                endReached = items.size() < PAGE_SIZE;
                boolean none = loadedCount == 0; empty.setVisibility(none ? View.VISIBLE : View.GONE); if (grid != null) grid.setVisibility(none ? View.GONE : View.VISIBLE);
            });
        });
    }

    private void showActions(MediaItem item) {
        pending = item;
        new AlertDialog.Builder(this)
                .setTitle(item.displayName)
                .setItems(new String[] {
                        getString(R.string.restore),
                        getString(R.string.delete_permanently)
                }, (dialog, which) -> {
                    if (which == 0) requestTrash(false, REQUEST_RESTORE);
                    else requestDelete();
                })
                .show();
    }

    private void requestTrash(boolean value, int requestCode) {
        if (pending == null) return;
        try {
            PendingIntent request = MediaStore.createTrashRequest(
                    getContentResolver(), Collections.singletonList(pending.uri), value);
            startIntentSenderForResult(request.getIntentSender(), requestCode, null, 0, 0, 0);
        } catch (Exception exception) {
            Log.e(TAG, "Unable to change trash state", exception);
        }
    }

    private void requestDelete() {
        if (pending == null) return;
        try {
            PendingIntent request = MediaStore.createDeleteRequest(
                    getContentResolver(), Collections.singletonList(pending.uri));
            startIntentSenderForResult(request.getIntentSender(), REQUEST_DELETE, null, 0, 0, 0);
        } catch (Exception exception) {
            Log.e(TAG, "Unable to permanently delete media", exception);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK
                && (requestCode == REQUEST_RESTORE || requestCode == REQUEST_DELETE)) {
            pending = null;
            load();
        }
    }

    @Override
    protected void onDestroy() {
        if (adapter != null) adapter.close();
        if (pageTask != null) pageTask.cancel(true);
        pageTask = null;
        executor.shutdownNow();
        super.onDestroy();
    }
}
