package com.lemenzo.gallery.favorites;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

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.viewer.ViewerActivity;

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

public final class FavoritesFragment extends Fragment {
    private GalleryAdapter adapter;
    private RecyclerView grid;
    private View empty;
    private FavoritesViewModel viewModel;
    private ExecutorService executor;
    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;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
        View view = inflater.inflate(R.layout.fragment_favorites, container, false);
        grid = view.findViewById(R.id.favorites_grid);
        empty = view.findViewById(R.id.empty_state);
        viewModel = new FavoritesViewModel(getActivity());
        executor = BackgroundExecutors.single("LemenzoGalleryFavorites");

        int columns = 3;
        GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), columns);
        adapter = new GalleryAdapter(getActivity(), new GalleryAdapter.Listener() {
            @Override
            public void onOpen(MediaItem item) {
                startActivity(ViewerActivity.intent(getActivity(), item));
            }

            @Override
            public void onSelectionChanged(int count) {}
        }, false);
        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();
        return view;
    }

    public void refresh() {
        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(), true);
        loadNextPage(true);
    }

    private void loadNextPage(boolean firstPage) {
        ExecutorService current = executor;
        if (current == null || current.isShutdown() || loadingPage || endReached) return;
        loadingPage = true; final MediaItem anchor = pageAnchor; final int generation = loadGeneration;
        pageTask = current.submit(() -> {
            List<MediaItem> items = viewModel.pageAfter(anchor, PAGE_SIZE);
            if (getActivity() == null) return;
            getActivity().runOnUiThread(() -> {
                if (generation != loadGeneration || adapter == null || grid == null || empty == null) return;
                loadingPage = false;
                if (firstPage) adapter.submit(items, true); else adapter.append(items, true);
                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); grid.setVisibility(none ? View.GONE : View.VISIBLE);
            });
        });
    }

    @Override
    public void onDestroyView() {
        if (adapter != null) adapter.close();
        adapter = null;
        if (pageTask != null) pageTask.cancel(true);
        pageTask = null;
        if (executor != null) executor.shutdownNow();
        executor = null;
        grid = null;
        empty = null;
        super.onDestroyView();
    }
}
