package com.codingotaku.apps;

import java.util.Collections;

import com.codingotaku.apis.animecrawler.Episode;
import com.codingotaku.apis.animecrawler.EpisodeList;
import com.codingotaku.apps.custom.DownloadDialog;
import com.codingotaku.apps.custom.Toast;
import com.codingotaku.apps.custom.Toast.Delay;
import com.codingotaku.apps.download.DownloadManager;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SelectionMode;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class EpisodeController {
	@FXML private Button downloadEp;
	@FXML private CheckBox cb;
	@FXML private ScrollPane epScrollPane;
	@FXML VBox root;

	private ListView<Episode> episodeList;
	private Stage stage;
	private VBox episodeBox;

	private final ObservableList<Episode> episodes = FXCollections.observableArrayList();
	private final DownloadManager manager = DownloadManager.getInstance();

	@FXML private void initialize() {
		episodeBox = (VBox) epScrollPane.getContent().lookup("#epList");
		cb.selectedProperty().addListener((paramObservableValue, old, flag) -> {
			if (episodeList == null)
				return;
			if (Boolean.TRUE.equals(flag))
				episodeList.getSelectionModel().selectAll();
			else
				episodeList.getSelectionModel().clearSelection();
		});
	}

	@FXML private void download(ActionEvent event) {
		int count = 0;

		if (episodeList != null) {
			count = episodeList.getSelectionModel().getSelectedItems().size();
		}

		var dialog = new DownloadDialog(count);

		if (stage == null)
			stage = (Stage) root.getScene().getWindow(); // an ugly way of initializing stage
		// Calculate the center position of the parent Stage
		double centerXPosition = stage.getX() + stage.getWidth() / 2d;
		double centerYPosition = stage.getY() + stage.getHeight() / 2d;

		dialog.setOnShowing(e -> {
			dialog.setX(centerXPosition - dialog.getDialogPane().getWidth() / 2d);
			dialog.setY(centerYPosition - dialog.getDialogPane().getHeight() / 2d);
		});

		var result = dialog.showAndWait();
		result.ifPresent(res -> {
			if (Boolean.TRUE.equals(res)) {
				ObservableList<Episode> selectedItems = episodeList.getSelectionModel().getSelectedItems();
				new Thread(() -> selectedItems.forEach(manager::addDownloadURL)).start();
				Toast.makeToast(stage, String.format("Downloading %d episode(s), check downloads tab for details.",
						selectedItems.size()), Delay.SHORT, Delay.VERY_SHORT, Delay.SHORT).show();
			}
		});
	}

	@FXML private void reverse() {
		if (episodeList != null) {
			ObservableList<Integer> list = episodeList.getSelectionModel().getSelectedIndices();
			Integer[] selected = new Integer[list.size()];
			list.toArray(selected);

			int size = episodeList.getItems().size() - 1;
			episodeList.getSelectionModel().clearSelection();
			Collections.reverse(episodeList.getItems());

			for (int sel : selected) { // Reverse selection
				episodeList.getSelectionModel().select(size - sel);
			}
		}
	}

	void setCheckBoxStatus(int selSize, int epSize) {
		if (selSize == 0) {
			cb.setIndeterminate(false);
			cb.setSelected(false);
		}

		if (selSize < epSize) {
			cb.setIndeterminate(true);
		} else {
			cb.setIndeterminate(false);
			cb.setSelected(true);
		}
	}

	void loadEpisodes(EpisodeList episodesTmp) {
		Platform.runLater(() -> {
			episodes.setAll(episodesTmp.episodes());
			episodeList = new ListView<>();
			episodeList.setItems(episodes);
			episodeList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
			episodeList.setOnMouseClicked(event -> {
				int selSize = episodeList.getSelectionModel().getSelectedIndices().size();
				this.setCheckBoxStatus(selSize, episodes.size());
			});
		});

		Platform.runLater(() -> {
			VBox.setVgrow(episodeList, Priority.ALWAYS);
			episodeBox.getChildren().setAll(episodeList);
		});

	}

	void setDownloadController(DownloadController downloadController) {
		manager.setController(downloadController);
	}
}