package ch.zhaw.gartenverwaltung;

import ch.zhaw.gartenverwaltung.gardenplan.Gardenplanmodel;
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
import ch.zhaw.gartenverwaltung.taskList.PlantNotFoundException;
import ch.zhaw.gartenverwaltung.taskList.TaskListModel;
import ch.zhaw.gartenverwaltung.types.GrowthPhaseType;
import ch.zhaw.gartenverwaltung.types.Plant;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.util.Callback;

import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.util.List;
import java.util.ResourceBundle;

public class SelectSowDayController implements Initializable {
    private Plant selectedPlant = null;
    private final TaskListModel taskListModel = new TaskListModel();
    private final Gardenplanmodel gardenplanmodel = new Gardenplanmodel(taskListModel);

    @FXML
    private DatePicker datepicker;

    @FXML
    private Label popup_label;

    @FXML
    private Button save_button;

    @FXML
    private RadioButton sow_radio;

    public SelectSowDayController() throws IOException {}

    /**
     * close the date selector window
     * @param event event
     */
    @FXML
    void cancel(ActionEvent event) {
        closeWindow();
    }

    /**
     * get sow date from datePicker or calculate sow date from harvest date
     * save selected plant and sow date
     * @param event event
     */
    @FXML
    void save(ActionEvent event) throws HardinessZoneNotSetException, IOException, PlantNotFoundException {
        LocalDate sowDate;
        if (sow_radio.isSelected()) {
            sowDate = datepicker.getValue();
        } else {
            //ToDo method to get current lifecycle group in plant
            sowDate = selectedPlant.sowDateFromHarvestDate(datepicker.getValue(), 0);
        }
        gardenplanmodel.plantAsCrop(selectedPlant, sowDate);
        closeWindow();
    }

    /**
     * save the plant which will be planted and update label
     * @param plant Plant
     */
    public void getSelectedPlant(Plant plant) {
        selectedPlant = plant;
        popup_label.setText("Select Harvest/Sow Date for" + selectedPlant.name());
    }

    /**
     * add listener and set default values
     * {@inheritDoc}
     * @param location location
     * @param resources resources
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        clearDatePickerEntries();

        Callback<DatePicker, DateCell> dayCellFactory= getDayCellFactory();
        datepicker.setDayCellFactory(dayCellFactory);
        datepicker.getEditor().setEditable(false);

        enableDisableSaveButton();
    }

    /**
     * clear date picker editor when radio button is changed
     */
    private void clearDatePickerEntries() {
        sow_radio.selectedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean isNowSelected) {
                datepicker.getEditor().clear();
            }
        });
    }

    /**
     * date picker disable/enable dates according to selected plant: sow or harvest day
     * @return cellFactory of datePicker
     */
    private Callback<DatePicker, DateCell> getDayCellFactory() {

        final Callback<DatePicker, DateCell> dayCellFactory = new Callback<DatePicker, DateCell>() {

            @Override
            public DateCell call(final DatePicker datePicker) {
                return new DateCell() {
                    @Override
                    public void updateItem(LocalDate item, boolean empty) {
                        super.updateItem(item, empty);
                        setDisable(true);
                        setStyle("-fx-background-color: #ffc0cb;");
                        List<LocalDate> dates;
                        LocalDate today = LocalDate.now();
                        if (sow_radio.isSelected()) {
                            dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.SOW);
                        } else {
                            dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.HARVEST);
                        }
                        for (LocalDate date : dates) {
                            if (item.getMonth() == date.getMonth()
                                    && item.getDayOfMonth() == date.getDayOfMonth()
                                    && item.compareTo(today) > 0) {
                                setDisable(false);
                                setStyle("-fx-background-color: #32CD32;");
                            }
                        }
                        if ((!sow_radio.isSelected() && selectedPlant.sowDateFromHarvestDate(item, 0).compareTo(today) < 0)) {
                            setDisable(true);
                            setStyle("-fx-background-color: #ffc0cb;");
                        }
                    }
                };
            }
        };
        return dayCellFactory;
    }

    /**
     * close date picker window
     */
    private void closeWindow() {
        Stage stage = (Stage) save_button.getScene().getWindow();
        stage.close();
    }

    /**
     * disable save button, when there is no date selected in date picker
     */
    private void enableDisableSaveButton() {
        save_button.setDisable(true);
        datepicker.getEditor().textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                if (newValue == null || newValue.equals("")) {
                    save_button.setDisable(true);
                } else {
                    save_button.setDisable(false);
                }
            }
        });
    }
}
