package controllers;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import data.GuiMysql;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableView.TableViewSelectionModel;
import javafx.scene.control.cell.MapValueFactory;
import objects.OverUnder;

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

	@FXML private TableView<Map<String, Object>> statsTable;

	@FXML TableColumn<Map, Float> diffColumn = new TableColumn<>("Diff");
	@FXML TableColumn<Map, String> u05 = new TableColumn<>("Under 0.5");
	@FXML TableColumn<Map, String> o05 = new TableColumn<>("Over 0.5");
	@FXML TableColumn<Map, String> u15 = new TableColumn<>("Under 1.5");
	@FXML TableColumn<Map, String> o15 = new TableColumn<>("Over 1.5");
	@FXML TableColumn<Map, String> u25 = new TableColumn<>("Under 2.5");
	@FXML TableColumn<Map, String> o25 = new TableColumn<>("Over 2.5");
	@FXML TableColumn<Map, String> u35 = new TableColumn<>("Under 3.5");
	@FXML TableColumn<Map, String> o35 = new TableColumn<>("Over 3.5");
	@FXML TableColumn<Map, String> u45 = new TableColumn<>("Under 4.5");
	@FXML TableColumn<Map, String> o45 = new TableColumn<>("Over 4.5");
	@FXML TableColumn<Map, String> u55 = new TableColumn<>("Under 5.5");
	@FXML TableColumn<Map, String> o55 = new TableColumn<>("Over 5.5");
	@FXML TableColumn<Map, String> u65 = new TableColumn<>("Under 6.5");
	@FXML TableColumn<Map, String> o65 = new TableColumn<>("Over 6.5");

	private ObservableList<Map<String, Object>> statLines;

	private static StatisticsTabController instance;

	public static StatisticsTabController getInstance() {
		if (instance == null) {
			synchronized (StatisticsTabController.class) {
				if (instance == null) {
					instance = new StatisticsTabController();
				}
			}
		}
		return instance;
	}

	@Override public void initialize(URL arg0, ResourceBundle arg1) {
		diffColumn.setCellValueFactory(new MapValueFactory<>("diff"));
		u05.setCellValueFactory(new MapValueFactory<>("u05"));
		o05.setCellValueFactory(new MapValueFactory<>("o05"));
		u15.setCellValueFactory(new MapValueFactory<>("u15"));
		o15.setCellValueFactory(new MapValueFactory<>("o15"));
		u25.setCellValueFactory(new MapValueFactory<>("u25"));
		o25.setCellValueFactory(new MapValueFactory<>("o25"));
		u35.setCellValueFactory(new MapValueFactory<>("u35"));
		o35.setCellValueFactory(new MapValueFactory<>("o35"));
		u45.setCellValueFactory(new MapValueFactory<>("u45"));
		o45.setCellValueFactory(new MapValueFactory<>("o45"));
		u55.setCellValueFactory(new MapValueFactory<>("u55"));
		o55.setCellValueFactory(new MapValueFactory<>("o55"));
		u65.setCellValueFactory(new MapValueFactory<>("u65"));
		o65.setCellValueFactory(new MapValueFactory<>("o65"));

		statLines = FXCollections.<Map<String, Object>>observableArrayList();
		instance = this;
	}

	public void setOverUnderTable(int leagueId, String gameDate) {
		final List<OverUnder> statsOverUnder = GuiMysql.getInstance().getStatsOverUnder(leagueId, gameDate);

		statLines.clear();
		for (final OverUnder ou : statsOverUnder) {
			final Map<String, Object> line = new HashMap<>();
			if (statLines.stream().noneMatch(p -> p.get("diff") == ou.getKey())) {
				line.put("diff", ou.getKey());
				line.put("u05", ou.getGoals().get(0) + " (" + ou.calcMinOdds(ou.getGoals().get(0)) + ")");
				line.put("o05", getOverStat(ou, 1) + " (" + ou.calcMinOdds(getOverStat(ou, 1)) + ")");
				line.put("u15", getUnderStat(ou, 2) + " (" + ou.calcMinOdds(getUnderStat(ou, 2)) + ")");
				line.put("o15", getOverStat(ou, 2) + " (" + ou.calcMinOdds(getOverStat(ou, 2)) + ")");
				line.put("u25", getUnderStat(ou, 3) + " (" + ou.calcMinOdds(getUnderStat(ou, 3)) + ")");
				line.put("o25", getOverStat(ou, 3) + " (" + ou.calcMinOdds(getOverStat(ou, 3)) + ")");
				line.put("u35", getUnderStat(ou, 4) + " (" + ou.calcMinOdds(getUnderStat(ou, 4)) + ")");
				line.put("o35", getOverStat(ou, 4) + " (" + ou.calcMinOdds(getOverStat(ou, 4)) + ")");
				line.put("u45", getUnderStat(ou, 5) + " (" + ou.calcMinOdds(getUnderStat(ou, 5)) + ")");
				line.put("o45", getOverStat(ou, 5) + " (" + ou.calcMinOdds(getOverStat(ou, 5)) + ")");
				line.put("u55", getUnderStat(ou, 6) + " (" + ou.calcMinOdds(getUnderStat(ou, 6)) + ")");
				line.put("o55", getOverStat(ou, 6) + " (" + ou.calcMinOdds(getOverStat(ou, 6)) + ")");
				line.put("u65", getUnderStat(ou, 7) + " (" + ou.calcMinOdds(getUnderStat(ou, 7)) + ")");
				line.put("o65", getOverStat(ou, 7) + " (" + ou.calcMinOdds(getOverStat(ou, 7)) + ")");

				statLines.add(line);
			}
		}
		statsTable.getItems().clear();
		statsTable.getItems().addAll(statLines);
		diffColumn.setSortable(true);
	}

	private int getUnderStat(OverUnder ou, float atMostXGoals) {
		final ArrayList<Integer> goals = ou.getGoals();
		int sum = 0;
		for (int i = 0; i < (goals.size() < atMostXGoals ? goals.size() : atMostXGoals); i++) {
			sum += goals.get(i);
		}
		return sum;
	}

	private int getOverStat(OverUnder ou, int atLeastXGoals) {
		final ArrayList<Integer> goals = ou.getGoals();
		int sum = 0;
		for (int i = atLeastXGoals; i < goals.size(); i++) {
			sum += goals.get(i);
		}
		return sum;
	}

	public void markValueInTable(float value) {
		TableViewSelectionModel<Map<String, Object>> selectionModel = statsTable.getSelectionModel();
		java.util.Optional<Map<String, Object>> optional = statsTable.getItems().stream().filter(p -> (Float) p.get("diff") == value).findFirst();
		if (optional.isPresent()) {
			selectionModel.setSelectionMode(SelectionMode.SINGLE);
			int indexOf = statsTable.getItems().indexOf(optional.get());
			selectionModel.select(indexOf);
		}
	}
}
