package controllers;

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.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;
import objects.League;
import objects.Percentages;
import objects.SoccerMatch;
import objects.SoccerMatchAnalysis;
import parser.Svenskaspel;

import java.math.RoundingMode;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.time.LocalDateTime;
import java.util.*;

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

    private static final DecimalFormat FLOAT_FORMATTER = new DecimalFormat("0.00");
    TableColumn<SoccerMatchAnalysis, String> homeTeamNameColumn = new TableColumn<>("Home Team");
    TableColumn<SoccerMatchAnalysis, String> awayTeamNameColumn = new TableColumn<>("Away Team");
    TableColumn<SoccerMatchAnalysis, String> leagueNameColumn = new TableColumn<>("Country");

    TableColumn<SoccerMatchAnalysis, String> countryNameColumn = new TableColumn<>("League");

    TableColumn<SoccerMatchAnalysis, Integer> scoringDiffLastGamesColumn = new TableColumn<>("Scoring Diff");
    TableColumn<SoccerMatchAnalysis, Integer> scoringTotalColumn = new TableColumn<>("Scoring Total");
    TableColumn<SoccerMatchAnalysis, Integer> winCountColumn = new TableColumn<>("Win Count");
    TableColumn<SoccerMatchAnalysis, Integer> winLossRatioColumn = new TableColumn<>("Win/loss Ratio");
    TableColumn<SoccerMatchAnalysis, Integer> percentagesColumn = new TableColumn<>("percentages");
    TableColumn<SoccerMatchAnalysis, Void> bet1Column = new TableColumn<>("1");
    TableColumn<SoccerMatchAnalysis, Void> betXColumn = new TableColumn<>("X");
    TableColumn<SoccerMatchAnalysis, Void> bet2Column = new TableColumn<>("2");

    @FXML
    TableView<SoccerMatchAnalysis> gameViewTable;
    @FXML
    Button getMatchesButton;
    @FXML
    DatePicker date;
    @FXML
    Button calculateTestData;

    Map<String, League> leagueInfoMap = new HashMap<>();

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        FLOAT_FORMATTER.setRoundingMode(RoundingMode.UP);
        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.ENGLISH);
        dfs.setDecimalSeparator('.');
        dfs.setGroupingSeparator(',');
        FLOAT_FORMATTER.setDecimalFormatSymbols(dfs);

        date.valueProperty().addListener((observable, oldValue, newValue) -> {
            if (oldValue != newValue) {
                gameViewTable.getItems().clear();
            }
        });

        homeTeamNameColumn.setCellValueFactory(new PropertyValueFactory<>("homeTeamName"));
        awayTeamNameColumn.setCellValueFactory(new PropertyValueFactory<>("awayTeamName"));
        leagueNameColumn.setCellValueFactory(new PropertyValueFactory<>("leagueName"));
        countryNameColumn.setCellValueFactory(new PropertyValueFactory<>("countryName"));
        scoringDiffLastGamesColumn.setCellValueFactory(new PropertyValueFactory<>("scoringDiffValue"));
        scoringTotalColumn.setCellValueFactory(new PropertyValueFactory<>("scoringTotal"));
        winCountColumn.setCellValueFactory(new PropertyValueFactory<>("winCount"));
        winLossRatioColumn.setCellValueFactory(new PropertyValueFactory<>("winLossRatio"));
        percentagesColumn.setCellValueFactory(new PropertyValueFactory<>("percentages"));

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

                            private final CheckBox checkbox = new CheckBox();

                            {
                                checkbox.setOnAction((ActionEvent event) -> {
                                    SoccerMatch 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(checkbox);
                                }
                            }

                        };
                    }
                };

        bet1Column.setCellFactory(cellFactory);
        betXColumn.setCellFactory(cellFactory);
        bet2Column.setCellFactory(cellFactory);

        gameViewTable.getColumns().addAll(homeTeamNameColumn, awayTeamNameColumn, countryNameColumn, leagueNameColumn,
                scoringDiffLastGamesColumn, scoringTotalColumn, winCountColumn, winLossRatioColumn, percentagesColumn,
                bet1Column, betXColumn, bet2Column);
        gameViewTable.setEditable(true);
    }

    private void addToBets(SoccerMatch data) {
        // TODO
    }

    private void addMatchesToTable(List<SoccerMatchAnalysis> matches) {
        ObservableList<SoccerMatchAnalysis> currentMatches = FXCollections.<SoccerMatchAnalysis>observableArrayList();

        GuiMysql db = GuiMysql.getInstance();
        for (SoccerMatchAnalysis match : matches) {
            League l = db.getLeagueInfo(match.getHomeTeam().getTeamLeagueId());
            Percentages percentages = new Percentages();
            int homeScore = match.scoringTotal(l.getScoringTotal(), true);
            int awayScore = match.scoringTotal(l.getScoringTotal(), false);

            db.getTotalGoalStat(percentages, l.getLeagueId(),l.getScoringTotal(),
                    homeScore - awayScore);

            db.getScoringDiffLastGames(percentages, l.getLeagueId(), l.getScoringDiffLastGame(),
                    match.getScoringDiffLastGames(l.getScoringDiffLastGame()));

            int winLossHAHome = match.winLossRatioHomeAndAway(true, l.getWinLossRatioHomeAndAway());
            int winLossHAAway = match.winLossRatioHomeAndAway(false, l.getWinLossRatioHomeAndAway());
            db.getWinLossRatioHomeAndAwayStatistics(percentages, l.getLeagueId(), l.getWinLossRatioHomeAndAway(),
                    winLossHAHome-winLossHAAway);

            int winLossHome = match.winLossRatio(l.getWinLossRatio(), true);
            int winLossAway = match.winLossRatio(l.getWinLossRatio(), false);
            match.winLossRatio(l.getWinLossRatio(), false);
            db.getWinLossRatioStatisticsGames(percentages,l.getLeagueId(),l.getWinLossRatio(),winLossHome-winLossAway);

            match.setPercentages(percentages.getCalculation());
        }
        currentMatches.addAll(matches);

        gameViewTable.getItems().addAll(currentMatches);
    }

    @FXML
    private void GetMatchesAction() {
        List<SoccerMatchAnalysis> matches = GuiMysql.getInstance().getMatchesForStryktipset(date.getValue().toString());

        if (matches.isEmpty()) {
            Svenskaspel parser = new parser.Svenskaspel();
            matches = parser.GetStryktipsetSelenium(date.getValue().toString());
        }

        for (SoccerMatchAnalysis match : matches) {
            League info = getLeagueInfo(match, match.getHomeTeam().getTeamLeague());
            match.setLeagueName(match.getHomeTeam().getTeamLeague());
            match.setCountryName(match.getHomeTeam().getCountryName());
            match.setScoringDiffValue(match.getScoringDiffLastGames(info.getScoringDiffLastGame()));
            match.setScoringTotal(match.scoringTotal(info.getScoringTotal(), true) - match.scoringTotal(info.getScoringTotal(), false));
            match.setWinCount(match.winLossRatio(info.getWinLossRatio(), true) - match.winLossRatio(info.getWinLossRatio(), false));
            match.setWinLossRatio(match.winLossRatioHomeAndAway(true, info.getWinLossRatioHomeAndAway()) - match.winLossRatioHomeAndAway(false, info.getWinLossRatioHomeAndAway()));
        }

        addMatchesToTable(matches);
    }

    private League getLeagueInfo(SoccerMatch match, String leagueName) {
        League info = leagueInfoMap.get(leagueName);
        if (info == null) {
            info = GuiMysql.getInstance().getLeagueInfo(match.getHomeTeam().getTeamLeagueId());
            leagueInfoMap.put(leagueName, info);
        }
        return info;
    }

    @FXML
    private void calculateTestData() {

        List<League> prioLeagues = GuiMysql.getInstance().getLeaguesWithPrio();

        int i = 1;
        for (League l : prioLeagues) {

            System.out.println("Starting " + i++ + "/" + prioLeagues.size() + " " + LocalDateTime.now() + " with " +
                    l.getLeagueName());
/*            GuiMysql.getInstance().calculateWinLossRatioHomeAndAwayStat(l.getLeagueId(),
                    l.getWinLossRatioHomeAndAway()); */
GuiMysql.getInstance().addScoringDiffStatistics(l.getLeagueId(), l.getScoringDiffLastGame());
/*
                GuiMysql.getInstance().calculateWinLossRatioStat(l.getLeagueId(),
                    l.getWinLossRatioHomeAndAway());
                    */

            /*
            List<SoccerMatchAnalysis> matches = GuiMysql.getInstance().getSoccerMatchesWithGoalStats(l.getLeagueId(),
                    LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE), l.getScoringTotal());
            System.out.println("Finished " + LocalDateTime.now()+ " with " + l.getLeagueName());
            */
        }
    }
}
