package dendrarium.portal;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.ScrollableResults;

/**
 *
 * @author pta
 */
public class PaginatedList<T> implements Serializable {

    private List<T> all;

    private List<T> currentPage;

    private List<Integer> pageSeq1;

    private List<Integer> pageSeq2;

    private int pageNo = 0;

    private int pages;

    private int pageSize;

    private int size;

    public PaginatedList(List<T> all, int pageSize) {
        this.all = all;
        this.pageSize = pageSize;
        this.size = all.size();

        pages = (size % pageSize == 0) ? (size / pageSize) : (size / pageSize + 1);
        getPage(0);
    }

    /*public PaginatedList(ScrollableResults scrollable, int pageSize) {
        this.pageSize = pageSize;
        scrollable.last();
        this.size = scrollable.getRowNumber() + 1;

        pages = (size % pageSize == 0) ? (size / pageSize) : (size / pageSize + 1);
        getPage(scrollable, 0);
    }*/

    public PaginatedList(Long count, Query query, int pageSize) {
        size = count.intValue();
        this.pageSize = pageSize;
        pages = (size % pageSize == 0) ? (size / pageSize) : (size / pageSize + 1);
        getPage(query, 0);
    }

    public PaginatedList(Long count, Criteria query, int pageSize) {
        size = count.intValue();
        this.pageSize = pageSize;
        pages = (size % pageSize == 0) ? (size / pageSize) : (size / pageSize + 1);
        getPage(query, 0);
    }

    public void getPage(int page) {
        pageNo = page;
        createPageSeqs(pageNo, pages);

        int last = (pageNo + 1) * pageSize;

        currentPage = all.subList(pageNo * pageSize, last <= size ? last : size);
    }

    public void getPage(Query query, int page) {
        pageNo = page;
        createPageSeqs(pageNo, pages);

        //int last = (pageNo + 1) * pageSize;

        currentPage = query.setFirstResult(pageNo * pageSize).setMaxResults(pageSize).list();
    }

    public void getPage(Criteria query, int page) {
        pageNo = page;
        createPageSeqs(pageNo, pages);
        currentPage = query.setFirstResult(pageNo * pageSize).setMaxResults(pageSize).list();
    }

    public boolean isEmpty() {
        return size == 0;
    }

    // tego i tak się nigdzie nie używa (na szczęście)
    public List<T> getAll() {
        return all;
    }

    public List<T> getCurrentPage() {
        return currentPage;
    }

    public int getPageNo() {
        return pageNo;
    }

    public List<Integer> getPageSeq1() {
        return pageSeq1;
    }

    public List<Integer> getPageSeq2() {
        return pageSeq2;
    }

    public int getPageSize() {
        return pageSize;
    }

//    public void setPageSize(int pageSize) {
//        this.pageSize = pageSize;
//    }

    public int getPages() {
        return pages;
    }

    private void createPageSeqs(int pageNo, int pages) {
        pageSeq1 = new ArrayList<Integer>(pageNo > 0 ? pageNo : 0);
        for (int i = 0 ; i < pageNo ; ++i) {
            pageSeq1.add(i, i);
        }

        pageSeq2 = new ArrayList<Integer>(pages - pageNo - 1 > 0 ? pages - pageNo - 1 : 0);
        for (int i = pageNo + 1, j = 0 ; i < pages ; ++i, ++j) {
            pageSeq2.add(j, i);
        }
    }

    public int getSize() {
        return size;
    }
}
