package ch.zhaw.gartenverwaltung;

import ch.zhaw.gartenverwaltung.bootstrap.AfterInject;
import ch.zhaw.gartenverwaltung.bootstrap.Inject;
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
import ch.zhaw.gartenverwaltung.io.PlantList;
import ch.zhaw.gartenverwaltung.models.Garden;
import ch.zhaw.gartenverwaltung.models.GardenSchedule;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.util.Callback;

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

/**
 * Controller class for the TaskFormular.fxml file
 */
public class TaskFormularController implements Initializable {
    private Crop crop;
    private Plant plant;
    private Task task = null;

    @Inject
    private GardenSchedule gardenSchedule;
    @Inject
    private Garden garden;
    @Inject
    private PlantList plantList;

    @FXML
    private TextArea description_area;

    @FXML
    private DatePicker end_datePicker;

    @FXML
    private TextField interval_field;

    @FXML
    private DatePicker start_datePicker;

    @FXML
    private TextField taskName_field;

    @AfterInject
    @SuppressWarnings("unused")

    /**
     * returns the edited or added {@link Task}
     * @param crop {@link Crop} which was selected
     * @return {@link Task} which was edited or added
     */
    public Task returnResult(Crop crop) {
        int interval = 0;
        if (interval_field.getText() != null && !(interval_field.getText().isEmpty() || interval_field.getText().equals(""))) {
            interval = Integer.parseInt(interval_field.getText());
        }
        Task task = new Task(taskName_field.getText(), description_area.getText(),
                start_datePicker.getValue(), end_datePicker.getValue(),
                interval, crop.getCropId().get());
        if (this.task != null) return this.task.updateTask(task);
        return task;
    }

    /**
     * set selected crop and get the plant from the crop.
     * @param crop {@link Crop} which was selected
     * @throws HardinessZoneNotSetException exception
     * @throws IOException exception
     */
    public void setCorp(Crop crop) throws HardinessZoneNotSetException, IOException {
        this.crop = crop;
        this.plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get();
    }

    /**
     * set the values of task into the labels and datePicker.
     * @param task {@link Task} which was given
     */
    public void setTaskValue(Task task) {
        this.task = task;
        taskName_field.setText(task.getName());
        description_area.setText(task.getDescription());
        start_datePicker.setValue(task.getStartDate());
        end_datePicker.setValue(task.getEndDate().orElse(null));
        if(task.getInterval().orElse(null)!=null) {
            interval_field.setText(task.getInterval().get().toString());
        } else {
            interval_field.setText(null);
        }
    }

    /**
     * dayCellFactory of the start date
     * @return {@link Callback} of the dayCellFactory
     */
    private Callback<DatePicker, DateCell> getDayCellFactoryStartDate() {

        return (datePicker) -> new DateCell() {
            private final LocalDate today = LocalDate.now();

            @Override
            public void updateItem(LocalDate item, boolean empty) {
                super.updateItem(item, empty);
                setDisable(true);
                setStyle("-fx-background-color: #ffc0cb;");

                if (item.compareTo(today) > 0 && item.compareTo(crop.getStartDate()) > 0 && item.compareTo(crop.getStartDate().plusDays(plant.timeToHarvest(0))) < 0) {
                    setDisable(false);
                    setStyle("-fx-background-color: #32CD32;");
                }

                if (end_datePicker.getValue() != null && item.compareTo(end_datePicker.getValue()) > 0) {
                    setDisable(true);
                    setStyle("-fx-background-color: #ffc0cb;");
                }
            }
        };
    }

    /**
     * dayCellFactory of the end date
     * @return {@link Callback} of the dayCellFactory
     */
    private Callback<DatePicker, DateCell> getDayCellFactoryEndDate() {

        return (datePicker) -> new DateCell() {
            private final LocalDate today = LocalDate.now();

            @Override
            public void updateItem(LocalDate item, boolean empty) {
                super.updateItem(item, empty);
                setDisable(true);
                setStyle("-fx-background-color: #ffc0cb;");

                if (item.compareTo(today) > 0 && item.compareTo(crop.getStartDate()) > 0 && item.compareTo(crop.getStartDate().plusDays(plant.timeToHarvest(0))) < 0) {
                    setDisable(false);
                    setStyle("-fx-background-color: #32CD32;");
                }

                if (start_datePicker.getValue() != null && item.compareTo(start_datePicker.getValue()) < 0) {
                    setDisable(true);
                    setStyle("-fx-background-color: #ffc0cb;");
                }
            }
        };
    }

    /**
     * disable button until condition meet.
     * @param button {@link Button} which was given
     */
    public void initSaveButton(Button button) {
        interval_field.textProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue != null && !newValue.matches("\\d*")) {
                interval_field.setText(newValue.replaceAll("[^\\d]", ""));
            }
        });

        button.disableProperty().bind(start_datePicker.valueProperty().isNull()
                .or(taskName_field.textProperty().isEmpty())
                .or(description_area.textProperty().isEmpty()));
    }

    /**
     * initialize dayCellFactories
     * @param location
     * The location used to resolve relative paths for the root object, or
     * {@code null} if the location is not known.
     *
     * @param resources
     * The resources used to localize the root object, or {@code null} if
     * the root object was not localized.
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        start_datePicker.setDayCellFactory(getDayCellFactoryStartDate());
        start_datePicker.setEditable(false);

        end_datePicker.setDayCellFactory(getDayCellFactoryEndDate());
        end_datePicker.setEditable(false);
    }
}
