/*
 * Copyright (C) 2018-2020, 2022 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>.
 */

/*
	Change log
    2.9.6	When a Diary entry is added/changed, make sure updated comments are shown
    3.0.4	Add in delete() to enable new convenience class CatalogueNotebookBeanDeleter in the GUI.
 */

package uk.co.gardennotebook.fxbean;

import java.time.LocalDate;

import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.collections.ObservableList;
import uk.co.gardennotebook.spi.NotebookEntryType;
import uk.co.gardennotebook.util.StoryLineTree;
import uk.co.gardennotebook.spi.GNDBException;

/**
	*	
	*
	*	@author	Andy Gegg
	*	@version	3.0.4
	*	@since	1.0
*/
public interface INotebookBean
{

	/**
	*	get the primary key for the item this bean wraps
	*
	*	@return	 the primary key
	*/
	Integer getKey();

	/**
	*	get the type of the item this bean wraps
	*
	*	@return	 the item type
	*/
	NotebookEntryType getType();

	/**
	*	check if two beans reference the same persisted item
	*
	*	@param other	the bean to compare with this bean
	*
	*	@return	true if both beans reference the same item
	*/
	boolean sameAs(INotebookBean other);

	/**
	*	Check if the item is new, i.e. being created
	*
	*	@return	true if this is a new item
	*/
	boolean isNew();

	/**
	*	Check if the item is new, i.e. being created
	*
	*	@return	true if this is a new item
	*/
	ReadOnlyBooleanProperty isNewProperty();

	/**
	*	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>
	*/
	boolean canDelete() throws GNDBException;

	/**
	 *	Delete the underlying item.
	 *
	 *	@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>
	 *
	 * @since 3.0.4
	 */
	void delete() 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>
	*/
	ReadOnlyBooleanProperty canDeleteProperty() throws GNDBException;

	/**
	*	Check if the item has story line ancestors
	*
	*	@return	true if {@code getAncestors()} can be called safely
	*			false if there are no story line ancestors
	*
	*	@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>
	*/
	boolean hasAncestor() throws GNDBException;

	/**
	*	Check if the item has story line ancestors
	*
	*	@return	true if {@code getAncestors()} can be called safely
	*			false if there are no story line ancestors
	*
	*	@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>
	*/
	ReadOnlyBooleanProperty hasAncestorProperty() throws GNDBException;

	/**
	*	get the story line ancestors of the item this bean wraps
	*
	*	@return	 the list of ancestors, possibly an empty list
	*
	*	@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>
	*/
	StoryLineTree<? extends INotebookBean> getAncestors() throws GNDBException;

	/**
	*	Check if the item has story line descendants
	*
	*	@return	true if {@code getAncestors()} can be called safely
	*			false if there are no story line descendants
	*
	*	@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>
	*/
	boolean hasDescendant() throws GNDBException;

	/**
	*	Check if the item has story line descendants
	*
	*	@return	true if {@code getDescendants()} can be called safely
	*			false if there are no story line descendants
	*
	*	@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>
	*/
	ReadOnlyBooleanProperty hasDescendantProperty() throws GNDBException;

	/**
	*	get the story line descendants of the item this bean wraps
	*
	*	@return	 the list of descendants, possibly an empty list
	*
	*	@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>
	*/
	StoryLineTree<? extends INotebookBean> getDescendants() throws GNDBException;

	/**
	*	get the comments on the item this bean wraps
	*
	*	@return	 the list of comments, possibly an empty list
	*/
	ObservableList<CommentBean> getComments();

	//	2.9.6
	ReadOnlyStringProperty commentTextProperty();

	/**
	*	add a new comment to the item this bean wraps
	*
	*	@param	text	the text of the new comment.  The current date will be applied
	*		Empty strings or null values will be ignored.
	*
	*	@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>
	*/
	void addComment(String text)throws GNDBException;

	//	2.9.6
	/**
	 *	add a new comment to the item this bean wraps
	 *
	 *	@param	comment	the new comment to add.
	 *		A null value will be ignored (null-op).
	 *	    If the comment text in the CommentBean is null or blank the value will be ignored (null-op).
	 *
	 *	@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>
	 */
	void addComment(CommentBean comment) throws GNDBException;

	/**
	*	change the text of a comment on the item this bean wraps
	*
	*	@param	comment	the comment to be modified.
	*	@param	text	the new text of the comment.
	*		Empty strings or null values will be ignored and the comment unchanged.
	*
	*	@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>
	*/
	void changeCommentText(CommentBean comment, String text) throws GNDBException;

	/**
	*	change the date of a comment on the item this bean wraps
	*
	*	@param	comment	the comment to be modified.
	*	@param	date	the new date of the comment.
	*		Null values will be ignored and the comment unchanged.
	*
	*	@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>
	*/
	void changeCommentDate(CommentBean comment, LocalDate date)throws GNDBException;

	/**
	*	delete a comment on the item this bean wraps
	*
	*	@param	comment	the comment to be modified.
	*
	*	@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>
	*/
	void deleteComment(CommentBean comment)throws GNDBException;

	default boolean needSave()
	{
		return false;
	}

	/**
	 *	Save changes to the underlying NotebookBean item
	 *
	 *	@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>
	 */
	void save() throws GNDBException;
}

