001/*
002 * This file is part of Baritone.
003 *
004 * Baritone is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU Lesser General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * Baritone is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License
015 * along with Baritone.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package baritone.api.command.helpers;
019
020import baritone.api.command.argument.IArgConsumer;
021import baritone.api.command.exception.CommandException;
022import baritone.api.command.exception.CommandInvalidTypeException;
023import baritone.api.utils.Helper;
024import net.minecraft.util.text.ITextComponent;
025import net.minecraft.util.text.TextComponentString;
026import net.minecraft.util.text.TextFormatting;
027import net.minecraft.util.text.event.ClickEvent;
028import net.minecraft.util.text.event.HoverEvent;
029
030import java.util.Arrays;
031import java.util.List;
032import java.util.function.Function;
033
034public class Paginator<E> implements Helper {
035
036    public final List<E> entries;
037    public int pageSize = 8;
038    public int page = 1;
039
040    public Paginator(List<E> entries) {
041        this.entries = entries;
042    }
043
044    public Paginator(E... entries) {
045        this.entries = Arrays.asList(entries);
046    }
047
048    public Paginator<E> setPageSize(int pageSize) {
049        this.pageSize = pageSize;
050        return this;
051    }
052
053    public int getMaxPage() {
054        return (entries.size() - 1) / pageSize + 1;
055    }
056
057    public boolean validPage(int page) {
058        return page > 0 && page <= getMaxPage();
059    }
060
061    public Paginator<E> skipPages(int pages) {
062        page += pages;
063        return this;
064    }
065
066    public void display(Function<E, ITextComponent> transform, String commandPrefix) {
067        int offset = (page - 1) * pageSize;
068        for (int i = offset; i < offset + pageSize; i++) {
069            if (i < entries.size()) {
070                logDirect(transform.apply(entries.get(i)));
071            } else {
072                logDirect("--", TextFormatting.DARK_GRAY);
073            }
074        }
075        boolean hasPrevPage = commandPrefix != null && validPage(page - 1);
076        boolean hasNextPage = commandPrefix != null && validPage(page + 1);
077        ITextComponent prevPageComponent = new TextComponentString("<<");
078        if (hasPrevPage) {
079            prevPageComponent.getStyle()
080                    .setClickEvent(new ClickEvent(
081                            ClickEvent.Action.RUN_COMMAND,
082                            String.format("%s %d", commandPrefix, page - 1)
083                    ))
084                    .setHoverEvent(new HoverEvent(
085                            HoverEvent.Action.SHOW_TEXT,
086                            new TextComponentString("Click to view previous page")
087                    ));
088        } else {
089            prevPageComponent.getStyle().setColor(TextFormatting.DARK_GRAY);
090        }
091        ITextComponent nextPageComponent = new TextComponentString(">>");
092        if (hasNextPage) {
093            nextPageComponent.getStyle()
094                    .setClickEvent(new ClickEvent(
095                            ClickEvent.Action.RUN_COMMAND,
096                            String.format("%s %d", commandPrefix, page + 1)
097                    ))
098                    .setHoverEvent(new HoverEvent(
099                            HoverEvent.Action.SHOW_TEXT,
100                            new TextComponentString("Click to view next page")
101                    ));
102        } else {
103            nextPageComponent.getStyle().setColor(TextFormatting.DARK_GRAY);
104        }
105        ITextComponent pagerComponent = new TextComponentString("");
106        pagerComponent.getStyle().setColor(TextFormatting.GRAY);
107        pagerComponent.appendSibling(prevPageComponent);
108        pagerComponent.appendText(" | ");
109        pagerComponent.appendSibling(nextPageComponent);
110        pagerComponent.appendText(String.format(" %d/%d", page, getMaxPage()));
111        logDirect(pagerComponent);
112    }
113
114    public void display(Function<E, ITextComponent> transform) {
115        display(transform, null);
116    }
117
118    public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Runnable pre, Function<T, ITextComponent> transform, String commandPrefix) throws CommandException {
119        int page = 1;
120        consumer.requireMax(1);
121        if (consumer.hasAny()) {
122            page = consumer.getAs(Integer.class);
123            if (!pagi.validPage(page)) {
124                throw new CommandInvalidTypeException(
125                        consumer.consumed(),
126                        String.format(
127                                "a valid page (1-%d)",
128                                pagi.getMaxPage()
129                        ),
130                        consumer.consumed().getValue()
131                );
132            }
133        }
134        pagi.skipPages(page - pagi.page);
135        if (pre != null) {
136            pre.run();
137        }
138        pagi.display(transform, commandPrefix);
139    }
140
141    public static <T> void paginate(IArgConsumer consumer, List<T> elems, Runnable pre, Function<T, ITextComponent> transform, String commandPrefix) throws CommandException {
142        paginate(consumer, new Paginator<>(elems), pre, transform, commandPrefix);
143    }
144
145    public static <T> void paginate(IArgConsumer consumer, T[] elems, Runnable pre, Function<T, ITextComponent> transform, String commandPrefix) throws CommandException {
146        paginate(consumer, Arrays.asList(elems), pre, transform, commandPrefix);
147    }
148
149    public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Function<T, ITextComponent> transform, String commandPrefix) throws CommandException {
150        paginate(consumer, pagi, null, transform, commandPrefix);
151    }
152
153    public static <T> void paginate(IArgConsumer consumer, List<T> elems, Function<T, ITextComponent> transform, String commandPrefix) throws CommandException {
154        paginate(consumer, new Paginator<>(elems), null, transform, commandPrefix);
155    }
156
157    public static <T> void paginate(IArgConsumer consumer, T[] elems, Function<T, ITextComponent> transform, String commandPrefix) throws CommandException {
158        paginate(consumer, Arrays.asList(elems), null, transform, commandPrefix);
159    }
160
161    public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Runnable pre, Function<T, ITextComponent> transform) throws CommandException {
162        paginate(consumer, pagi, pre, transform, null);
163    }
164
165    public static <T> void paginate(IArgConsumer consumer, List<T> elems, Runnable pre, Function<T, ITextComponent> transform) throws CommandException {
166        paginate(consumer, new Paginator<>(elems), pre, transform, null);
167    }
168
169    public static <T> void paginate(IArgConsumer consumer, T[] elems, Runnable pre, Function<T, ITextComponent> transform) throws CommandException {
170        paginate(consumer, Arrays.asList(elems), pre, transform, null);
171    }
172
173    public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Function<T, ITextComponent> transform) throws CommandException {
174        paginate(consumer, pagi, null, transform, null);
175    }
176
177    public static <T> void paginate(IArgConsumer consumer, List<T> elems, Function<T, ITextComponent> transform) throws CommandException {
178        paginate(consumer, new Paginator<>(elems), null, transform, null);
179    }
180
181    public static <T> void paginate(IArgConsumer consumer, T[] elems, Function<T, ITextComponent> transform) throws CommandException {
182        paginate(consumer, Arrays.asList(elems), null, transform, null);
183    }
184}