package ru.yandex.webmaster3.core.util;

/**
 * @author aherman
 */
public class PageUtils {
    public static interface Pager {
        public int getPage();
        public int getPageSize();
        public int toRangeStart();

        public boolean isEmpty();
    }

    public static interface LongPager {
        public int getPage();
        public int getPageSize();
        public long toRangeStart();

        public boolean isEmpty();
    }

    private static class NormalPage implements Pager {
        private final int page;
        private final int pageSize;

        private NormalPage(int page, int pageSize) {
            this.page = page;
            this.pageSize = pageSize;
        }

        @Override public int getPage() {return page;}
        @Override public int getPageSize() {return pageSize;}
        @Override public int toRangeStart() {return page * pageSize;}
        @Override public boolean isEmpty() {return false;}
    }

    private static class LongPagerImpl implements LongPager {
        private final int page;
        private final int pageSize;

        private LongPagerImpl(int page, int pageSize) {
            this.page = page;
            this.pageSize = pageSize;
        }

        @Override
        public int getPage() {
            return page;
        }

        @Override
        public int getPageSize() {
            return pageSize;
        }

        @Override
        public long toRangeStart() {
            return page * pageSize;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }
    }

    private static final Pager EMPTY_PAGE = new Pager() {
        @Override
        public int getPage() {
            throw new UnsupportedOperationException("Empty page");
        }

        @Override
        public int getPageSize() {
            throw new UnsupportedOperationException("Empty page");
        }

        @Override
        public int toRangeStart() {
            throw new UnsupportedOperationException("Empty page");
        }

        @Override
        public boolean isEmpty() {
            return true;
        }
    };

    private static final LongPager EMPTY_LONG_PAGE = new LongPager() {
        @Override
        public int getPage() {
            throw new UnsupportedOperationException("Empty page");
        }

        @Override
        public int getPageSize() {
            throw new UnsupportedOperationException("Empty page");
        }

        @Override
        public long toRangeStart() {
            throw new UnsupportedOperationException("Empty page");
        }

        @Override
        public boolean isEmpty() {
            return true;
        }
    };

    public static Pager getPage(int page, int pageSize, int totalItems) {
        if (page < 0 || page * pageSize > totalItems) {
            return new Pager() {
                @Override public int getPage() {throw new UnsupportedOperationException("Empty page");}
                @Override public int getPageSize() {throw new UnsupportedOperationException("Empty page");}
                @Override public int toRangeStart() {throw new UnsupportedOperationException("Empty page");}
                @Override public boolean isEmpty() {return true;}
            };
        }

        return new NormalPage(page, pageSize);
    }

    public static LongPager getPage(int page, int pageSize, long totalItems) {
        if (totalItems == 0) {
            return EMPTY_LONG_PAGE;
        }
        if (page < 0) {
            return EMPTY_LONG_PAGE;
        }
        if (page * pageSize > totalItems) {
            return EMPTY_LONG_PAGE;
        }

        return new LongPagerImpl(page, pageSize);
    }

    /**
     * @param page value in rage [0, inf)
     * @param pageSize value in range [1, 100]
     * @return
     */
    public static Pager getPage(int page, int pageSize) {
        if (page < 0) {
            page = 0;
        }

        if (pageSize > 100) {
            pageSize = 100;
        }

        if (pageSize < 1) {
            pageSize = 10;
        }
        return new NormalPage(page, pageSize);
    }
}
