/*
 * Copyright (C) 2021 Andrew Gegg
 *
 *	This file is part of the Garden Notebook application
 *
 * The Garden 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 uk.co.gardennotebook.util.StoryLineTree;

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

/**
*	These are the various locations where gardening events take place.
*

*	Use this class to create, modify or delete an instance of Location

*/

public interface ILocationBuilder
{
	/**
	*	set the  Location parent
	*
	*	@param	newVal	the new value
	*	@return	 this Builder
	*/
	public ILocationBuilder parentLocation(ILocation newVal);

	/**
	*	check if a value for name is already a key for an item of this type
	*
	*	@param	newVal	the value to check
	*	@return	true if the test value is already used as a unique key
	*
	*	@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 isNameDuplicate(final String newVal) throws GNDBException;

	/**
	*	give the (new) value of name
	*
	*	@param	newVal	the new value
	*	@return	this Builder
	*	@throws	IllegalArgumentException	if newVal already exists as a name
	*	@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 ILocationBuilder name(final String newVal) throws IllegalArgumentException, GNDBException;

	/**
	*	give the (new) value of description
	*
	*	@param	newVal	the new value
	*	@return	this Builder
	*/
	public ILocationBuilder description(final String newVal);

	/**
	 * 	Set the underCover flag for the Location
	 */
	public ILocationBuilder underCover(final boolean underCover);

	/**
	 *	give the (new) value of the geometry
	 *
	 *	@param	newVal	the new value
	 *	@return	this Builder
	 */
	public ILocationBuilder geometry(final String newVal);

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

	/**
	*	Add these values as new comments
	*
	*	@param	newVals	the new value
	*	@return	this Builder
	*/
	public ILocationBuilder addComment(final 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 ILocationBuilder deleteComment(final 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 ILocationBuilder deleteComment(final 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 ILocationBuilder changeComment(final 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 ILocationBuilder changeComment(final 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 ILocationBuilder changeComment(final 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 ILocation 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;

	/**
	*	check if this Location has any subordinate locations
	*
	*	@return	true if this Location is parent of any other Location
	*
	*	@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 hasChild() throws GNDBException;


}

