package controllers;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.text.DecimalFormat;
import java.time.format.DateTimeFormatter;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.NotImplementedException;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import data.GuiMysql;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.text.Text;
import javafx.util.Callback;
import objects.Constants;
import objects.League;
import objects.SoccerMatch;
import objects.SoccerMatchAnalysis;
import tests.objects.Standing;

@SuppressWarnings("rawtypes")
public class PastResultsController implements Initializable {

    @FXML
    AnchorPane basePane;
    @FXML
    TableView<Map<String, Object>> matchTable;
    @FXML
    DatePicker date;
    @FXML
    ComboBox<String> countrySelector;
    @FXML
    ComboBox<String> leagueSelector;

    @FXML
    TableColumn<Map, String> gameDateColumn = new TableColumn<>("Gamedate");
    @FXML
    TableColumn<Map, String> homeTeamColumn = new TableColumn<>("Home Team");
    @FXML
    TableColumn<Map, String> awayTeamColumn = new TableColumn<>("Away Team");
    @FXML
    TableColumn<Map, Float> odds1Column = new TableColumn<>("odds 1");
    @FXML
    TableColumn<Map, Float> oddsXColumn = new TableColumn<>("odds X");
    @FXML
    TableColumn<Map, Float> odds2Column = new TableColumn<>("odds 2");
    @FXML
    TableColumn<Map, Float> goalsHomeColumn = new TableColumn<>("Goals home");
    @FXML
    TableColumn<Map, Float> goalsAwayColumn = new TableColumn<>("Goals away");
    @FXML
    TableColumn<Map, Float> goalDiff = new TableColumn<>("Difference");
    @FXML
    TableColumn<Map, Float> avgScoreHomeColumn = new TableColumn<>("Avg score home");
    @FXML
    TableColumn<Map, Float> avgConcededHomeColumn = new TableColumn<>("Avg conceded home");
    @FXML
    TableColumn<Map, Float> avgScoreAwayColumn = new TableColumn<>("Avg score away");
    @FXML
    TableColumn<Map, Float> avgConcededAwayColumn = new TableColumn<>("Avg conceded away");

    @FXML
    TableColumn<Map, String> avgHomeScoredSeason = new TableColumn<>("AvgHomeScoredThisSeason");
    @FXML
    TableColumn<Map, String> avgHomeConcededSeason = new TableColumn<>("AvgHomeConcededThisSeason");

    @FXML
    TableColumn<Map, String> avgAwayScoredSeason = new TableColumn<>("AvgAwayScoredThisSeason");
    @FXML
    TableColumn<Map, String> avgAwayConcededSeason = new TableColumn<>("AvgAwayConcededThisSeason");

    @FXML
    TableColumn<Map, String> sumScoringColumn = new TableColumn<>("Sum scoring");
    @FXML
    TableColumn<Map, Float> positionAdjustmentColumn = new TableColumn<>("PositionAdjustment");
    @FXML
    TableColumn<Map, String> newScoringTestColumn = new TableColumn<>("New Scoring test");
    @FXML
    TableColumn<Map, Void> addToBetsButtonColumn = new TableColumn<>("Add bet");
    @FXML
    TableColumn<Map, String> analysisColumn = new TableColumn<>("Analysis");

    @FXML
    Text homeTeamPastResultsText;
    @FXML
    Text awayTeamPastResultsText;
    @FXML
    Text previousMeetingsText;
    @FXML
    Text previousReverseMeetingsText;

    @FXML
    Label NumberOfGamesText;
    @FXML
    TextArea SystemsText;
    @FXML
    Label ReslutsText;

    ObservableList<String> sports = FXCollections.observableArrayList();
    ObservableList<String> countries = FXCollections.observableArrayList();
    ObservableList<String> leagues = FXCollections.observableArrayList();

    private final ArrayList<SimpleEntry<Integer, String>> sportsList = Lists.newArrayList();
    private final ArrayList<SimpleEntry<Integer, String>> countriesList = Lists.newArrayList();
    private final ArrayList<SimpleEntry<Integer, String>> leaguesList = Lists.newArrayList();

    GuiMysql db = GuiMysql.getInstance();
    private String selectedHomeTeam;
    private String selectedAwayTeam;

    Set<betSystemDTO> bets = new HashSet<>();
    private League leagueInfo;

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        gameDateColumn.setCellValueFactory(new MapValueFactory<>("gameDate"));
        homeTeamColumn.setCellValueFactory(new MapValueFactory<>("homeTeam"));
        awayTeamColumn.setCellValueFactory(new MapValueFactory<>("awayTeam"));
        odds1Column.setCellValueFactory(new MapValueFactory<>("odds1"));
        oddsXColumn.setCellValueFactory(new MapValueFactory<>("oddsX"));
        odds2Column.setCellValueFactory(new MapValueFactory<>("odds2"));
        goalsHomeColumn.setCellValueFactory(new MapValueFactory<>("goalsHome"));
        goalsAwayColumn.setCellValueFactory(new MapValueFactory<>("goalsAway"));
        goalDiff.setCellValueFactory(new MapValueFactory<>("goalDiff"));
        avgScoreHomeColumn.setCellValueFactory(new MapValueFactory<>("avgScoreHome"));
        avgConcededHomeColumn.setCellValueFactory(new MapValueFactory<>("avgConcededHome"));
        avgScoreAwayColumn.setCellValueFactory(new MapValueFactory<>("avgScoreAway"));
        avgConcededAwayColumn.setCellValueFactory(new MapValueFactory<>("avgConcededAway"));

        avgHomeScoredSeason.setCellValueFactory(new MapValueFactory<>("avgScoredHomeSeason"));
        avgHomeConcededSeason.setCellValueFactory(new MapValueFactory<>("avgConcededHomeSeason"));
        avgAwayScoredSeason.setCellValueFactory(new MapValueFactory<>("avgScoredAwaySeason"));
        avgAwayConcededSeason.setCellValueFactory(new MapValueFactory<>("avgConcededAwaySeason"));

        sumScoringColumn.setCellValueFactory(new MapValueFactory<>("sumScoring"));
        positionAdjustmentColumn.setCellValueFactory(new MapValueFactory<>("positionAdjustment"));
        newScoringTestColumn.setCellValueFactory(new MapValueFactory<>("newScoringTest"));
        analysisColumn.setCellValueFactory(new MapValueFactory<>("analysis"));

        Callback<TableColumn<Map, Void>, TableCell<Map, Void>> cellFactory = new Callback<TableColumn<Map, Void>, TableCell<Map, Void>>() {
            @Override
            public TableCell<Map, Void> call(final TableColumn<Map, Void> param) {
                return new TableCell<Map, Void>() {

                    private final Button btn = new Button("Submit");
                    {
                        btn.setOnAction((ActionEvent event) -> {
                            Map data = getTableView().getItems().get(getIndex());

                            addToBets(data);
                        });
                    }

                    @Override
                    public void updateItem(Void item, boolean empty) {
                        super.updateItem(item, empty);
                        if (empty) {
                            setGraphic(null);
                        } else {
                            setGraphic(btn);
                        }
                    }
                };
            }
        };

        addToBetsButtonColumn.setCellFactory(cellFactory);

        basePane.setPrefWidth(0.0);
        basePane.setPrefHeight(0.0);

        date.valueProperty().addListener((ov, oldValue, newValue) -> {
            clear();
            getCountriesAtDate();
        });

        sportsList.addAll(GuiMysql.getInstance().getSports());
        sports.add(MainController.SPORT);
        for (final SimpleEntry<Integer, String> entry : sportsList) {
            if (entry.getValue().equals("soccer")) { // Anv�nder just nu bara Soccer
                sports.add(entry.getValue());
            }
        }

        countrySelector.setItems(countries);
        leagueSelector.setItems(leagues);

        matchTable.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
            updateMatchStats(newSelection);
        });
    }

    public void addToBets(Map data) {
        String betType;
        if (Float.valueOf(data.get("sumScoring").toString()) > 5.0f
                && Float.valueOf(data.get("newScoringTest").toString()) > 6.5f) {
            betType = "O 1.5";
        } else if (Float.valueOf(data.get("sumScoring").toString()) < 2.0f
                && Float.valueOf(data.get("newScoringTest").toString()) < 3.5f) {
            betType = "U 3.5";
        } else if (Float.valueOf(data.get("sumScoring").toString()) < 3.0f
                && Float.valueOf(data.get("newScoringTest").toString()) < 4.5f) {
            betType = "U 4.5";
        } else {
            return;
        }

        bets.add(new betSystemDTO(Integer.valueOf(data.get("id").toString()),
                Integer.valueOf(data.get("homeScore").toString()),
                Integer.valueOf(data.get("awayScore").toString()), betType));
        increaseNumberOfBets();
        calculateSystems();
    }

    private void increaseNumberOfBets() {
        NumberOfGamesText.setText(String.valueOf(Integer.valueOf(NumberOfGamesText.getText()) + 1));
    }

    private void calculateSystems() {
        Set<Set<betSystemDTO>> combinations = Sets.powerSet(bets);

        combinations = combinations.stream().sorted((s1, s2) -> Integer.compare(s1.size(), s2.size()))
                .collect(Collectors.toSet());

        String combinationText = "";
        int totalCombinations = 0;
        Map<Integer, Integer> sets = new HashMap<>();
        for (Set<betSystemDTO> set : combinations) {
            if (set.size() > 0) {
                totalCombinations += set.size();
                sets.put(set.size(), sets.getOrDefault(set.size(), 0) + 1);
            }
        }

        String text = "Total Combinations: " + sets.values().stream().mapToInt(Integer::intValue).sum() + "\n";
        StringBuilder sb = new StringBuilder();
        sets.forEach((k, v) -> sb.append(k.toString() + "'s: " + v.toString() + "\n"));

        text += sb.toString();
        SystemsText.setText(text);
    }

    private void updateMatchStats(Map<String, Object> newSelection) {
        if (newSelection != null) {
            Map<String, String> previousMatches = db.getPreviousMatches(5, newSelection.get("homeTeam").toString(),
                    newSelection.get("awayTeam").toString(), date.getValue().toString(), getCountryIdFromSelector(),
                    getLeagueIdFromSelector());
            homeTeamPastResultsText.setText(previousMatches.get("PrevHomeTeam"));
            awayTeamPastResultsText.setText(previousMatches.get("PrevAwayTeam"));
            previousMeetingsText.setText(previousMatches.get("PrevCombined"));
            previousReverseMeetingsText.setText(previousMatches.get("PrevReversedCombined"));

            selectedHomeTeam = newSelection.get("homeTeam").toString();
            selectedAwayTeam = newSelection.get("awayTeam").toString();
            MatchStatTabController.getInstance().clearSelection();
            MatchStatTabController.getInstance().setTeamSelected(selectedHomeTeam, true);
            MatchStatTabController.getInstance().setTeamSelected(selectedAwayTeam, false);

            StatisticsTabController.getInstance()
                    .markValueInTable(((BigDecimal) newSelection.get("goalDiff")).floatValue());
        }
    }

    private void clear() {
        matchTable.getItems().clear();
        countriesList.clear();
        leaguesList.clear();
        countries.clear();
        leagues.clear();
    }

    private void getCountriesAtDate() {
        countriesList.clear();
        countriesList.addAll(GuiMysql.getInstance().getCountriesBySport(db.getSportId(MainController.SPORT),
                date.getValue().toString()));

        countriesList.forEach(c -> countries.add(c.getValue()));
    }

    private void getLeaguesAtDate(int countryId) {
        leaguesList.clear();
        leaguesList.addAll(db.getLeaguesByDate(db.getSportId("soccer"), countryId, date.getValue().toString()));

        leaguesList.forEach(l -> leagues.add(l.getValue()));
    }

    @FXML
    private void getResults() {
        throw new NotImplementedException();
    }

    @FXML
    private void countrySelected(ActionEvent event) {
        if (getCountryIdFromSelector() > 0) {
            getLeaguesAtDate(getCountryIdFromSelector());
            leagueSelector.setDisable(false);
        }
    }

    private int getCountryIdFromSelector() {
        Optional<SimpleEntry<Integer, String>> o = countriesList.stream()
                .filter(p -> p.getValue().equals(countrySelector.getValue())).findFirst();
        return o.isPresent() ? o.get().getKey() : -1;
    }

    private int getLeagueIdFromSelector() {
        Optional<SimpleEntry<Integer, String>> o = leaguesList.stream()
                .filter(p -> p.getValue().equals(leagueSelector.getValue())).findFirst();
        return o.isPresent() ? o.get().getKey() : -1;
    }

    private float getAvgGoalsWithSameDiff(int countryId, int leagueId, int placementDiff) {
        List<Standing> tempStanding = new ArrayList<>();
        float result = 0.0f;
        int matchedMatches = 0;

        if (placementDiff == 0) {
            return 0f;
        }

        List<SoccerMatch> matchesBefore = GuiMysql.getInstance().getMatches(1, countryId, leagueId,
                date.getValue().toString(), "ASC", false, false);

        for (SoccerMatch match : matchesBefore) {
            Optional<Standing> homeTeamStanding = tempStanding.stream()
                    .filter(ts -> ts.getTeamName().equals(match.getHomeTeam().getTeamName()))
                    .findFirst();
            Optional<Standing> awayTeamStanding = tempStanding.stream()
                    .filter(ts -> ts.getTeamName().equals(match.getAwayTeam().getTeamName()))
                    .findFirst();

            if (homeTeamStanding.isPresent() && awayTeamStanding.isPresent()) {
                int homeTeamPosition = tempStanding.indexOf(homeTeamStanding.get());
                int awayTeamPosition = tempStanding.indexOf(awayTeamStanding.get());

                int diff = Math.abs(homeTeamPosition - awayTeamPosition);

                if (diff == placementDiff) {
                    matchedMatches++;
                    result += match.getHomeScore() + match.getAwayScore();
                }
            }
            updateStanding(tempStanding, match,
                    tempStanding.stream().filter(p -> p.getTeamName().equals(match.getHomeTeam().getTeamName()))
                            .findFirst(),
                    tempStanding.stream().filter(p -> p.getTeamName().equals(match.getAwayTeam().getTeamName()))
                            .findFirst());

            tempStanding.sort((s1, s2) -> Integer.compare(s2.getPoints(), s1.getPoints()));
        }

        return matchedMatches > 0 ? result / matchedMatches : 0f;
    }

    private void updateStanding(List<Standing> result, SoccerMatch match, Optional<Standing> homeTeam,
            Optional<Standing> awayTeam) {
        int homeScore = match.getHomeScore();
        int awayScore = match.getAwayScore();
        if (homeScore > awayScore) {
            homeTeam.ifPresentOrElse(ht -> {
                ht.setWins(ht.getWins() + 1);
                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
                ht.setPoints(ht.getPoints() + 3);
            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));

            awayTeam.ifPresentOrElse(at -> {
                at.setLosses(at.getLosses() + 1);
                at.setGamesPlayed(at.getGamesPlayed() + 1);
            }, () -> result.add(new Standing(match.getAwayTeam().getTeamName(), 0, 0, 1, 0, 1)));

        } else if (homeScore == awayScore) {

            homeTeam.ifPresentOrElse(ht -> {
                ht.setDraws(ht.getDraws() + 1);
                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
                ht.setPoints(ht.getPoints() + 1);
            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
            awayTeam.ifPresentOrElse(at -> {
                at.setDraws(at.getDraws() + 1);
                at.setGamesPlayed(at.getGamesPlayed() + 1);
                at.setPoints(at.getPoints() + 1);
            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
        } else if (homeScore < awayScore) {
            homeTeam.ifPresentOrElse(ht -> {
                ht.setLosses(ht.getLosses() + 1);
                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 0, 1, 0, 1)));
            awayTeam.ifPresentOrElse(at -> {
                at.setWins(at.getWins() + 1);
                at.setGamesPlayed(at.getGamesPlayed() + 1);
                at.setPoints(at.getPoints() + 3);
            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
        }
    }

    @FXML
    private void leagueSelected(ActionEvent event) {
        updateStandingsTable();
        if (getCountryIdFromSelector() > 0) {
            List<SoccerMatch> matchesList = db.getMatches(db.getSportId(MainController.SOCCER),
                    getCountryIdFromSelector(),
                    db.getLeagueId(db.getSportId(MainController.SOCCER), getCountryIdFromSelector(),
                            leagueSelector.getValue()),
                    date.getValue().toString(), "ASC", true, false);

            leagueInfo = GuiMysql.getInstance().getLeagueInfo(getLeagueIdFromSelector());
            addMatchesToTable(matchesList);
        }
    }

    private void addMatchesToTable(List<SoccerMatch> matchesList) {
        ObservableList<Map<String, Object>> matches = FXCollections.<Map<String, Object>>observableArrayList();

        for (final SoccerMatch soccerMatch : matchesList) {

            final Map<String, Object> match = new HashMap<>();
            match.put("homeTeam", soccerMatch.getHomeTeam().getTeamName());
            match.put("awayTeam", soccerMatch.getAwayTeam().getTeamName());
            match.put("odds1", soccerMatch.getOdds1());
            match.put("oddsX", soccerMatch.getOddsX());
            match.put("odds2", soccerMatch.getOdds2());

            final List<Float> avgHomeTeamGoals = calculateAvgHomeScore(soccerMatch.getHomeTeam().getTeamId());
            final List<Float> avgAwayTeamGoals = calculateAvgAwayScore(soccerMatch.getAwayTeam().getTeamId());

            final List<Float> avgHomeTeamGoalsThisSeason = calculateAvgHomeScoreThisSeason(
                    soccerMatch.getHomeTeam().getTeamId(),
                    soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getTeamLeagueId());
            final List<Float> avgAwayTeamGoalsThisSeason = calculateAvgAwayScoreThisSeason(
                    soccerMatch.getAwayTeam().getTeamId(),
                    soccerMatch.getAwayTeam().getCountryId(), soccerMatch.getAwayTeam().getTeamLeagueId());

            match.put("gameDate", soccerMatch.getGameDate().toString());
            match.put("avgScoreHome", avgHomeTeamGoals.get(0));
            match.put("avgConcededHome", avgHomeTeamGoals.get(1));
            match.put("avgScoreAway", avgAwayTeamGoals.get(0));
            match.put("avgConcededAway", avgAwayTeamGoals.get(1));

            match.put("avgScoredHomeSeason", avgHomeTeamGoalsThisSeason.get(0));
            match.put("avgConcededHomeSeason", avgHomeTeamGoalsThisSeason.get(1));

            match.put("avgScoredAwaySeason", avgAwayTeamGoalsThisSeason.get(0));
            match.put("avgConcededAwaySeason", avgAwayTeamGoalsThisSeason.get(1));

            match.put("sumScoring", avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1)
                    + avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1));

            match.put("goalsHome",
                    GuiMysql.getInstance().round(
                            BigDecimal.valueOf(avgHomeTeamGoalsThisSeason.get(0) + avgAwayTeamGoalsThisSeason.get(1)),
                            GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
            match.put("goalsAway",
                    GuiMysql.getInstance().round(
                            BigDecimal.valueOf(avgAwayTeamGoalsThisSeason.get(0) + avgHomeTeamGoalsThisSeason.get(1)),
                            GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));

            match.put("goalDiff",
                    GuiMysql.getInstance()
                            .round(BigDecimal
                                    .valueOf((avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1))
                                            + (avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1))),
                                    GuiMysql.getInstance().getIncrement(),
                                    RoundingMode.HALF_UP));
            match.put("country", soccerMatch.getHomeTeam().getCountryName());

            List<Float> leagueAvarages = GuiMysql.getInstance().getLeagueAvarages(getLeagueIdFromSelector(),
                    getCountryIdFromSelector(),
                    soccerMatch.getGameDate().format(DateTimeFormatter.BASIC_ISO_DATE));
            match.put("positionAdjustment", getAvgGoalsWithSameDiff(soccerMatch.getHomeTeam().getCountryId(),
                    soccerMatch.getHomeTeam().getTeamLeagueId(), MatchStatTabController.getInstance()
                            .getTeamPositionDiff(soccerMatch.getHomeTeam().getTeamName(),
                                    soccerMatch.getAwayTeam().getTeamName()))
                    - (leagueAvarages.get(0) + leagueAvarages.get(1)));

            match.put("newScoringTest",
                    (avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1)
                            + avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1))
                            + ((avgHomeTeamGoals.get(0) * avgAwayTeamGoals.get(1))
                                    + avgAwayTeamGoals.get(0) * avgHomeTeamGoals.get(1)) / 2);

            SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
            if (leagueInfo == null || leagueInfo.getLeagueId() != soccerMatch.getHomeTeam().getTeamLeagueId()) {
                leagueInfo = GuiMysql.getInstance().getLeagueInfo(soccerMatch.getHomeTeam().getTeamLeagueId());
            }
            if (leagueInfo != null) {
                int homeWinsCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), true);
                int awayWindCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), false);

                int homeWinLossRatioCount = analysis.winLossRatioHomeAndAway(true,
                        leagueInfo.getWinLossRatioHomeAndAway());
                int awayWinLossRatioCount = analysis.winLossRatioHomeAndAway(false,
                        leagueInfo.getWinLossRatioHomeAndAway());

                int homeScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), true);
                int awayScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), false);

                int scoringDiffLastGames = analysis.getScoringDiffLastGames(leagueInfo.getScoringDiffLastGame());
                int winsCountDiff = homeWinsCount - awayWindCount;
                int winLossRatioDiff = homeWinLossRatioCount - awayWinLossRatioCount;
                int scoringTotalDiff = homeScoringTotal - awayScoringTotal;

                int testValue = 0;
                if (scoringDiffLastGames < 0 && winsCountDiff < 0 && winLossRatioDiff < 0 && scoringTotalDiff < 0) {
                    testValue = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
                    match.put("analysis", testValue);
                } else if (scoringDiffLastGames > 0 && winsCountDiff > 0 && winLossRatioDiff > 0
                        && scoringTotalDiff > 0) {
                    testValue = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
                    match.put("analysis", testValue);
                } else {
                    match.put("analysis", "NoBet");
                }
            }

            match.put(Constants.LEAGUE, soccerMatch.getHomeTeam().getTeamLeague());

            match.put("id", soccerMatch.getMatchId());
            match.put("homeScore", soccerMatch.getHomeScore());
            match.put("awayScore", soccerMatch.getAwayScore());
            final DecimalFormat df = new DecimalFormat("#.##");
            df.setRoundingMode(RoundingMode.CEILING);

//			final League leagueInfo = GuiMysql.getInstance().getLeagueInfo(soccerMatch.getHomeTeam().getTeamLeague());

            matches.add(match);
        }
        matchTable.getItems().addAll(matches);
    }

    private List<Float> calculateAvgHomeScore(int teamId) {
        return GuiMysql.getInstance().getAvgHomeScore(teamId);
    }

    private List<Float> calculateAvgAwayScore(int teamId) {
        return GuiMysql.getInstance().getAvgAwayScore(teamId);
    }

    private List<Float> calculateAvgHomeScoreThisSeason(int teamId, int countryId, int leagueId) {
        return GuiMysql.getInstance().getAvgHomeScoreThisSeason(teamId, countryId, leagueId,
                date.getValue().toString());
    }

    private List<Float> calculateAvgAwayScoreThisSeason(int teamId, int countryId, int leagueId) {
        return GuiMysql.getInstance().getAvgAwayScoreThisSeason(teamId, countryId, leagueId,
                date.getValue().toString());
    }

    @FXML
    private void updateStatsTable() {
        StatisticsTabController.getInstance().setOverUnderTable(getLeagueIdFromSelector(), date.getValue().toString());
    }

    @FXML
    private void updateStandingsTable() {
        int countryId = getCountryIdFromSelector();
        if (countryId > 0) {
            String seasonFromDate = GuiMysql.getInstance().getSeasonFromDate(countryId, getLeagueIdFromSelector(),
                    date.getValue().toString());
            MatchStatTabController.getInstance().setLeagueStandingsTable(getLeagueIdFromSelector(), seasonFromDate,
                    countryId,
                    date.getValue().toString());
        }
    }

    @FXML
    private void getAllMatchesAtDate() {
        String dateString = date.getValue().toString();

        List<SoccerMatch> matches = GuiMysql.getInstance().getMatches(1, dateString, "ASC", true);
        addMatchesToTable(matches);
    }

    @FXML
    private void ClearBetSlip() {
        NumberOfGamesText.setText("0");
        SystemsText.setText("");
        ReslutsText.setText("");
        bets.clear();
    }

    @FXML
    private void CheckBetSlip() {
        Set<Set<betSystemDTO>> combinations = Sets.powerSet(bets);

        Map<Integer, Integer> resultWins = new HashMap<>();
        Map<Integer, Integer> resultLosses = new HashMap<>();

        int setTest = 0;
        double betAmount = 10.0d;

        Map<Integer, Double> banks = new HashMap<>();

        for (Set<betSystemDTO> set : combinations) {
            if (set.size() > 0) {
                System.out.println("Set " + ++setTest);
                if (set.stream().allMatch(this::isWin)) {
                    resultWins.put(set.size(), resultWins.getOrDefault(set.size(), 0) + 1);
                    set.forEach(s -> {
                        System.out.println(
                                "WIN size " + set.size() + " GameId: " + s.getGameId() + " Score " + s.getHomeScore()
                                        + " - " + s.getAwayScore());
                        banks.put(set.size(), banks.getOrDefault(set.size(), 0d)
                                + ((betAmount * Math.pow(1.15d, set.size())) - betAmount));
                    });

                } else { // Set/combination lost
                    resultLosses.put(set.size(), resultLosses.getOrDefault(set.size(), 0) + 1);
                    set.forEach(s -> System.out.println("LOSS size " + set.size() + " GameId: " + s.getGameId()
                            + " Score " + s.getHomeScore() + " - "
                            + s.getAwayScore() + " type " + s.getBetType()));
                    banks.put(set.size(), banks.getOrDefault(set.size(), 0d) - betAmount);
                }
            }
        }

        StringBuilder losses = new StringBuilder();
        StringBuilder wins = new StringBuilder();
        StringBuilder bankString = new StringBuilder();

        resultLosses.forEach((k, v) -> losses.append("Set size: " + k + " number of losses: " + v + "\n"));
        resultWins.forEach((k, v) -> wins.append("Set size: " + k + " number of Wins: " + v + "\n"));
        banks.forEach((k, v) -> bankString.append("Set " + k + " result " + v + "\n"));

        System.out.println(
                "Results \n WINS \n" + wins.toString() + "\nLOSSES\n" + losses.toString() + "\nBanks:" + bankString);
    }

    public boolean isWin(betSystemDTO bet) {
        boolean result = false;
        String betType = bet.getBetType();
        String overUnder = betType.substring(0, 1);
        float res = Float.valueOf(betType.substring(2, betType.length()));
        int gameGoals = bet.getHomeScore() + bet.getAwayScore();

        if (overUnder.equals("O")) {
            if (gameGoals > res) {
                result = true;
            }
        } else if (overUnder.equals("U")) {
            if (gameGoals < res) {
                result = true;
            }
        }
        return result;
    }

    class betSystemDTO {
        int gameId;
        int homeScore;
        int awayScore;
        String betType;

        public betSystemDTO(int gameId, int homeScore, int awayScore, String betType) {
            super();
            this.gameId = gameId;
            this.homeScore = homeScore;
            this.awayScore = awayScore;
            this.betType = betType;
        }

        public int getGameId() {
            return gameId;
        }

        public void setGameId(int gameId) {
            this.gameId = gameId;
        }

        public int getHomeScore() {
            return homeScore;
        }

        public void setHomeScore(int homeScore) {
            this.homeScore = homeScore;
        }

        public int getAwayScore() {
            return awayScore;
        }

        public void setAwayScore(int awayScore) {
            this.awayScore = awayScore;
        }

        public String getBetType() {
            return betType;
        }

        public void setBetType(String betType) {
            this.betType = betType;
        }

    }
}
