package components.betsequences;

import components.AjaxButtonPanel;
import data.BetStrategyMysql.BetStrategyMysql;
import data.DTO.FibonacciDTO.FibonacciDTO;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.*;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.resource.PackageResourceReference;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class BetSequencesTable extends Panel {
    List<FibonacciDTO> allOpenFibonacciSequences;

    List<IColumn<FibonacciDTO, String>> tableColumns = new ArrayList<>();
    public BetSequencesTable(String id) {
        super(id);

        Label label = new Label("betSequencesLabel", "Current bet sequences");
        add(label);
        getData();
        
        buildGui();
    }

    @Override
    public void renderHead(IHeaderResponse response) {
        super.renderHead(response);

        PackageResourceReference cssFile = new PackageResourceReference(this.getClass(), "BetSequencesTable.css");
        CssHeaderItem cssItem = CssHeaderItem.forReference(cssFile);

        response.render(cssItem);
    }

    private void buildGui() {
        SortableDataProvider<FibonacciDTO, String> dataProvider = new SortableDataProvider<FibonacciDTO, String>() {
            @Override
            public Iterator<FibonacciDTO> iterator(long first, long count) {
                return allOpenFibonacciSequences.stream()
                        .collect(Collectors.collectingAndThen(
                            Collectors.toMap(FibonacciDTO::getSequenceNumber,
                                    allOpen -> allOpen, (existing, replacement) -> existing),
                                map -> new ArrayList<>(map.values())
                                        .stream()
                                        .sorted(Comparator.comparingInt(FibonacciDTO::getSequenceNumber))
                                        .iterator()));
            }

            @Override
            public long size() {
                return allOpenFibonacciSequences.size();
            }

            @Override
            public IModel<FibonacciDTO> model(FibonacciDTO object) {
                return Model.of(object);
            }
        };
        Form<?> form = new Form<>("form");
        add(form);

        DataTable<FibonacciDTO, String> dataTable = new DataTable<>("betSequencesTable", tableColumns, dataProvider, 10);

        dataTable.addTopToolbar(new HeadersToolbar<>(dataTable, dataProvider));
        form.add(dataTable);
        add(form);
    }

    private void getData() {
        allOpenFibonacciSequences = BetStrategyMysql.getInstance().getAllOpenFibonacciSequences();

        tableColumns.add(new PropertyColumn<>(Model.of("Sequence Number"), "sequenceNumber", "sequenceNumber"));
        tableColumns.add(new LambdaColumn<>(Model.of("Match Sequence"), fibonacciDTO -> {
            List<FibonacciDTO> matches = allOpenFibonacciSequences.stream().filter(ao -> ao.getSequenceNumber() == fibonacciDTO.getSequenceNumber()).collect(Collectors.toList());
            return matches.stream().map(m -> m.getHomeTeamName() + " - " + m.getAwayTeamName()).collect(Collectors.joining(", "));
                }));
        tableColumns.add(new LambdaColumn<>(Model.of("Sequence length"), "match", fibonacciDTO -> {
            List<FibonacciDTO> matches = allOpenFibonacciSequences.stream().filter(ao -> ao.getSequenceNumber() == fibonacciDTO.getSequenceNumber()).collect(Collectors.toList());
            return matches.size();
        }));
        tableColumns.add(new LambdaColumn<>(Model.of("Next bet size"), "sequenceNumber",  f -> f.getNextSequenceNumber((int)allOpenFibonacciSequences.stream().filter(ao -> ao.getSequenceNumber() == f.getSequenceNumber()).count())));

        tableColumns.add(new LambdaColumn<FibonacciDTO, String>(Model.of("Action"), rowModel -> "action") {
            @Override
            public void populateItem(Item<ICellPopulator<FibonacciDTO>> cellItem, String componentId, IModel<FibonacciDTO> rowModel) {
                cellItem.add(new AjaxButtonPanel(componentId, rowModel));
            }
        });

    }
}