/*
 *
 *  Copyright (C) 2021 Andrew Gegg
 *
 * 	This file is part of the Gardeners Notebook application
 *
 *  The Gardeners Notebook application is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 *
 */

package uk.co.gardennotebook.spi;

import java.time.LocalDate;
import java.time.Year;
import java.util.List;

/**
 * This records the type of crop grown in a given location in a given planting year.  For instance, 'Alliums' in 'Bed 1'
 * in 2021.  Details of the actual plant species and, possibly, varieties can be added through the CroppingActual table.
 * Entries for past years are records of what was grown, entries for future years are to record the intended rotation of
 * crops through the various beds; the intention is that more detail is added (in CroppingActual) as plants are
 * ordered and sown.
 *
 *	@author	Andy Gegg
 *	@version	3.0.0
 *	@since	3.0.0
 */

public interface ICroppingPlanBuilder
{
    /**
     *	set the  CropRotationGroup parent
     *
     *	@param	newVal	the new value
     *	@return	 this Builder
     */
    public ICroppingPlanBuilder cropRotationGroup(ICropRotationGroup newVal);

    /**
     *	set the  Location parent
     *
     *	@param	newVal	the new value
     *	@return	 this Builder
     */
    public ICroppingPlanBuilder location(ILocation newVal);

    /**
     * Give the year being planned.
     * Default is the current calendar year.
     *
     * @param   yearOfPlan    the year being reviewed
     * @return  this builder
     */
    public ICroppingPlanBuilder yearOfPlan(Year yearOfPlan);

    /**
     * Check if the plan duplicates another plan
     * i.e. same yearOfPlan, Location and CropRotationGroup (all 3 must be the same)
     *
     * @return  true    if the Plan is a duplicate
     *
     *	@throws	GNDBException	if the underlying persisted storage engine (e.g. database server) throws an exception
     *				The original error can be retrieved by <code>getCause()</code>
     */
    public boolean isPlanDuplicate() throws GNDBException;

    /**
     *	Add this value as a comment; may be called multiple times
     *
     *	@param	newVals	the new value
     *	@return	this Builder
     */
    public ICroppingPlanBuilder addComment(String... newVals);

    /**
     *	Add these values as new comments
     *
     *	@param	newVals	the new value
     *	@return	this Builder
     */
    public ICroppingPlanBuilder addComment(List<String> newVals);

    /**
     *	remove one or more comments from this item
     *
     *	@param	oldVals	the comment to remove.  If the comment does not exist, this is a null-op
     *	@return	this Builder
     */
    public ICroppingPlanBuilder deleteComment(IComment... oldVals);

    /**
     *	remove a comment from this item
     *
     *	@param	oldVals	the comment to remove.  If the comment does not exist, this is a null-op
     *	@return	this Builder
     */
    public ICroppingPlanBuilder deleteComment(List<IComment> oldVals);

    /**
     *	modify a comment on this item
     *
     *	@param	base	the comment to modify.  If the comment does not exist, this is a null-op
     *	@param	comment	the replacement text
     *	@return	this Builder
     */
    public ICroppingPlanBuilder changeComment(IComment base, String comment);

    /**
     *	modify a comment on this item
     *
     *	@param	base	the comment to modify.  If the comment does not exist, this is a null-op
     *	@param	date	the replacement date
     *	@return	 this Builder
     */
    public ICroppingPlanBuilder changeComment(IComment base, LocalDate date);

    /**
     *	modify a comment on this item
     *
     *	@param	base	the comment to modify.  If the comment does not exist, this is a null-op
     *	@param	date	the replacement date
     *	@param	comment	the replacement text
     *	@return	this Builder
     */
    public ICroppingPlanBuilder changeComment(IComment base, LocalDate date, String comment);

    /**
     *	Check if the new or changed item needs to be saved
     *	i.e. has anything been changed?
     *
     *	@see #canSave()
     *
     *	@return	true if {@code save()} should be called
     *			false if nothing has been changed
     */
    public boolean needSave();

    /**
     *	Check if the new or changed item can be saved
     *	i.e. do all mandatory fields have a value?
     *
     *	@see #needSave()
     *
     *	@return	true if {@code save()} can be called safely
     *			false if there are unset mandatory values
     */
    public boolean canSave();

    /**
     *	Persist the new or changed instance to permanent storage
     *
     *	@return	A reference to the newly created or updated object
     *
     *	@throws	GNDBException	if the underlying persisted storage engine (e.g. database server) throws an exception
     *				The original error can be retrieved by <code>getCause()</code>
     */
    public ICroppingPlan save() throws GNDBException;

    /**
     *	Check if the item can be deleted
     *	i.e. are there any 'children' items?
     *
     *	@return	true if {@code delete()} can be called safely
     *			false if there are any 'children' items
     *
     *	@throws	GNDBException	if the underlying persisted storage engine (e.g. database server) throws an exception
     *				The original error can be retrieved by <code>getCause()</code>
     */
    public boolean canDelete() throws GNDBException;

    /**
     *	Delete the instance from permanent storage
     *
     *	@throws	GNDBException	if the underlying persisted storage engine (e.g. database server) throws an exception
     *				The original error can be retrieved by <code>getCause()</code>
     */
    public void delete() throws GNDBException;

}
