package controllers;

import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.AbstractMap.SimpleEntry;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;

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

import data.GuiMysql;
import exceptions.SportSelectionException;
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.ChoiceBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import objects.SoccerMatch;
import org.eclipse.jetty.util.log.Log;
import parser.OddsPortal;

public class MainController implements Initializable {

	public static final String SPORT = "Sport";
	public static final String SOCCER = "soccer";
	public static final String LEAGUE = "League";
	public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
	@FXML private MatchTabController matchTabController;
	@FXML private StatisticsTabController statTabController;
	@FXML private MatchStatTabController matchStatTabController;

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

	@FXML private ComboBox<String> sportSelector;
	@FXML private ComboBox<String> countrySelector;
	@FXML private ComboBox<String> leagueSelector;
	@FXML private ChoiceBox<String> homeTeamSelector;
	@FXML private ChoiceBox<String> awayTeamSelector;
	@FXML private Button resetFilterButton;
	@FXML private Button getLeagueInfoButton;
	@FXML private Button getMoreLeagueInfo;
	@FXML private Button updateStatsTableButton;
	@FXML private Button showMatchStatsButton;
	@FXML private TextField avgLeagueHomeScoreTxt;
	@FXML private TextField avgLeagueAwayScoreTxt;
	@FXML public TextField league0Goals;
	@FXML public TextField league1Goals;
	@FXML public TextField league2Goals;
	@FXML public TextField league3Goals;
	@FXML public TextField league4Goals;
	@FXML public TextField league5Goals;
	@FXML public TextField league6Goals;

	@FXML private Pane glass;

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

	@SuppressWarnings("unchecked")
	@Override public void initialize(URL arg0, ResourceBundle arg1) {
		sportsList = GuiMysql.getInstance().getSports();
		sports.add(SPORT);
		for (final SimpleEntry<Integer, String> entry : sportsList) {
			if (entry.getValue().equals(SOCCER)) { // Anv�nder just nu bara Soccer
				sports.add(entry.getValue());
			}
		}

		matchTabController.getTable().getSelectionModel().selectedItemProperty()
				.addListener((obs, oldSelection, newSelection) -> showMatchStatsButton.setDisable(newSelection == null));

		sportSelector.setItems(sports);
		countrySelector.setItems(countries);
		leagueSelector.setItems(leagues);
	}

	@FXML private void sportSelected(ActionEvent event) {
		if (sportSelector.getValue() != null && !sportSelector.getValue().equals(SPORT)) {
			countrySelector.setDisable(false);
			List<SoccerMatch> upcomingMatches = GuiMysql.getInstance().getUpcomingMatches("SoccerResults");

			matchTabController.setUpcomingMatches(upcomingMatches);

			countriesList.clear();
			for (final SoccerMatch soccerMatch : upcomingMatches) {
				homeTeams.add(soccerMatch.getHomeTeam().getTeamName());
				awayTeams.add(soccerMatch.getAwayTeam().getTeamName());

				if (countriesList.stream().noneMatch(p -> p != null && p.getValue().equals(soccerMatch.getHomeTeam().getCountryName()))) {
					countriesList.add(new SimpleEntry<>(soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getCountryName()));
				}
			}

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

			homeTeamSelector.setItems(homeTeams);
			awayTeamSelector.setItems(awayTeams);
		}
	}

	@FXML private void countrySelected(ActionEvent event) {
		if (countrySelector.getValue() != null && !countrySelector.getValue().equals("Country")) {
			leagueSelector.setDisable(false);
			final int countryId = getCountryIdFromSelector();
			Optional<SimpleEntry<Integer, String>> selectedSport = sportsList.stream().filter(p -> p.getValue().equals(sportSelector.getValue()))
					.findFirst();
			if (selectedSport.isPresent()) {
				final int sportId = selectedSport.get().getKey();
				matchTabController.filterCountryMatches(countrySelector.getValue());

				leaguesList = GuiMysql.getInstance().getLeagues(sportId, countryId);
				final List<String> leaguesInTable = Lists.newArrayList();
				matchTabController.getTableMatches().forEach(tr -> leaguesInTable.add(tr.getLeagueName()));
				final HashSet<String> newHashSet = Sets.newHashSet(leaguesInTable);

				leagues.clear();
				leagues.add(LEAGUE);
				leagues.addAll(newHashSet);
			} else {
				throw new SportSelectionException("No sport found");
			}

		}
	}

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

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

	@FXML private void leagueSelected(ActionEvent event) {

		if (leagueSelector.getValue() != null && !leagueSelector.getValue().equals(LEAGUE)) {
			homeTeamSelector.setDisable(false);
			awayTeamSelector.setDisable(false);
			showMatchStatsButton.setDisable(false);
			league6Goals.setText("0"); // Reset because adding
			if (GuiMysql.getInstance().getParsingStarted(getCountryIdFromSelector(), getLeagueIdFromSelector())) {
				getLeagueInfoButton.setDisable(true);
				getMoreLeagueInfo.setDisable(false);
			} else {
				getLeagueInfoButton.setDisable(false);
				getMoreLeagueInfo.setDisable(true);
			}
			matchTabController.filterLeagueMatches(leagueSelector.getValue(), getCountryIdFromSelector());
			updateStatsTableButton.setDisable(false);
			final List<Float> leagueAvareges = GuiMysql.getInstance().getLeagueAvarages(getLeagueIdFromSelector(), getCountryIdFromSelector(),
					DATE_FORMAT.format(new Date()));

			avgLeagueHomeScoreTxt.setText(leagueAvareges.get(0).toString());
			avgLeagueAwayScoreTxt.setText(leagueAvareges.get(1).toString());

			Map<Integer, Integer> goalAvgTheSeason = GuiMysql.getInstance().getGoalAvgThisSeason(getLeagueIdFromSelector(),
					getCountryIdFromSelector());

			league0Goals.setText(goalAvgTheSeason.getOrDefault(0, 0).toString());
			league1Goals.setText(goalAvgTheSeason.getOrDefault(1, 0).toString());
			league2Goals.setText(goalAvgTheSeason.getOrDefault(2, 0).toString());
			league3Goals.setText(goalAvgTheSeason.getOrDefault(3, 0).toString());
			league4Goals.setText(goalAvgTheSeason.getOrDefault(4, 0).toString());
			league5Goals.setText(goalAvgTheSeason.getOrDefault(5, 0).toString());
			for (int i = 6; i < goalAvgTheSeason.size(); i++) {
				addToMoreThan6Goals(goalAvgTheSeason.getOrDefault(i, 0));
			}

		} else {
			getMoreLeagueInfo.setDisable(true);
			getLeagueInfoButton.setDisable(true);
			updateStatsTableButton.setDisable(true);
			showMatchStatsButton.setDisable(true);
		}
	}

	private void addToMoreThan6Goals(Integer goals) {
		String startValue = league6Goals.getText();
		int intStartValue;
		if (startValue.length() <= 0) {
			intStartValue = 0;
		} else {
			intStartValue = Integer.parseInt(startValue);
		}

		league6Goals.setText(String.valueOf(intStartValue + goals));
	}

	@FXML private void resetFilter() {
		sportSelector.setValue(SPORT);
		countrySelector.setValue("Country");
		leagueSelector.setValue(LEAGUE);
		leagueSelector.setDisable(true);
		countrySelector.setDisable(true);
		matchTabController.resetFilter();
	}

	@FXML void getLeagueInfo() {
		final String country = countrySelector.getValue().trim();
		final String league = leagueSelector.getValue().trim();
		glass.setDisable(false);
		glass.setVisible(true);
		glass.setOpacity(0.8);
		final OddsPortal op = new OddsPortal();
		op.getHistoricMatches(sportSelector.getValue().trim(), country, league, String.valueOf(LocalDate.now().getYear()));
		glass.setOpacity(0.0);
		glass.setVisible(false);
		glass.setDisable(true);
	}

	@FXML private void updateStatsTable() {
		statTabController.setOverUnderTable(getLeagueIdFromSelector(), "");
	}

	@FXML private void getMoreLeagueInfo() {
		final String lastParsedYear = GuiMysql.getInstance().getLastParsedYear(leagueSelector.getValue().trim(), getCountryIdFromSelector());
		final String nextParseYear;
		if (lastParsedYear.contains("-")) {
			final String[] years = lastParsedYear.split("-");
			int firstYear = Integer.parseInt(years[0]);
			int lastYear = Integer.parseInt(years[1]);
			firstYear--;
			lastYear--;
			nextParseYear = firstYear + "-" + lastYear;
		} else if (lastParsedYear.length() == 4) {
			Integer val = Integer.valueOf(lastParsedYear);
			val--;
			nextParseYear = String.valueOf(val);
		} else {
			Log.getLogger("getMoreLeagueInfo").info("Fail to get More league info for %s", lastParsedYear);
			return;
		}

		final String country = countrySelector.getValue().trim();
		final String league = leagueSelector.getValue().trim();

		final OddsPortal op = new OddsPortal();
		op.getHistoricMatches(SOCCER, country, league, nextParseYear);
	}

	@FXML private void setMatchStatInfo() {
		final String season = GuiMysql.getInstance().getLastSeason(getCountryIdFromSelector(), getLeagueIdFromSelector());
		matchStatTabController.setLeagueStandingsTable(getLeagueIdFromSelector(), season, getCountryIdFromSelector(),
				new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
	}
}
