package ch.zhaw.gartenverwaltung.gardenplan;

import ch.zhaw.gartenverwaltung.io.GardenPlan;
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
import ch.zhaw.gartenverwaltung.io.JsonGardenPlan;
import ch.zhaw.gartenverwaltung.taskList.PlantNotFoundException;
import ch.zhaw.gartenverwaltung.taskList.TaskListModel;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Task;

import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;


/**
 * The Gardenplan model manages the crops in the gardenplan.
 */
public class Gardenplanmodel {
    private GardenPlan gardenPlan;
    private List<Crop> cropList;
    private TaskListModel taskListModel;
    private Object IllegalArgumentException;

    /**
     * Constructor of Gardenplan model
     *
     * @param taskListModel holds a reference to the task list object.
     */
    public Gardenplanmodel(TaskListModel taskListModel) throws IOException {
        this.taskListModel = taskListModel;
        gardenPlan = new JsonGardenPlan();
        cropList = new ArrayList<>();
        cropList = gardenPlan.getCrops();
    }

    /**
     * Creates a Crop with a {@link Plant} and the planting date of the plant. Then let the Tasklistmodel create the
     * gardening {@link Task} for the crop. Store the crop in the gardenplan file and the cache.
     *
     * @param plant The plant which is wnated to be planted
     * @param plantingDate The date, when the plant is planted
     * @throws IOException If the database cannot be accessed
     * @throws HardinessZoneNotSetException If the hardinesszone could not be added
     * @throws PlantNotFoundException If the plant is not found in the database.
     */
    public void plantAsCrop(Plant plant, LocalDate plantingDate) throws IOException, HardinessZoneNotSetException, PlantNotFoundException {
        Crop crop = new Crop(plant.id(), plantingDate);
        //TODO Add Area to Plant
        //crop.withArea(0);
        gardenPlan.saveCrop(crop);
        taskListModel.planTasksForCrop(crop);
        cropList = gardenPlan.getCrops();
    }

    /**
     * Removes a {@link Crop} from the file and the cache
     *
     * @param crop The plant which is wnated to be planted
     * @throws IOException If the database cannot be accessed
     */
    public void removeCrop(Crop crop) throws IOException {
        gardenPlan.removeCrop(crop);
        taskListModel.removeTasksForCrop(crop.getCropId().orElseThrow(IllegalArgumentException::new));
        cropList = gardenPlan.getCrops();
    }
    /**
     * Returns a list of {@link Crop}s which are currently in the gardenplan.
     *
     * @throws IOException If the database cannot be accessed
     */
    public List<Crop> getCrops() throws IOException {
        if(!cropList.isEmpty()){
                cropList = gardenPlan.getCrops();
        }
        return cropList;
    }

    /**
     * Returns an Optional of {@link Crop} if the crop is the gardenplan
     *
     * @param cropId The date, when the plant is planted
     * @throws IOException If the database cannot be accessed
     */
    public Optional<Crop> getCrop(Long cropId) throws IOException {
        return gardenPlan.getCropById(cropId);
    }
}
