/*
 * Copyright (C) 2018-2021, 2023 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.1.0 - handling for multiple servers for a given Trug - e.g. SQLTrug supports various RDBMSs
    2.8.1   Add method to detect empty database.
    3.0.0	Add support for new tables
    3.2.0	Add support for Lifecycle Analysis
 */

package uk.co.gardennotebook.spi;

import java.io.IOException;
import java.util.Map;
import java.util.Properties;

import java.util.prefs.Preferences;

/**
*	Defines a service which provides access to a persisted Garden Notebook.
*	The service is loaded using the Java Service Loader (see {@link TrugServer TrugServer})
*
*	@author	Andy Gegg
*	@version	3.2.0
*	@since	1.0
*/
public interface ITrug
{
	/**
	*	Return a display name for this service - such as MySQL, MariaDB, H2.
	*
	*	@return	a display name
	*/
	public String getName();

	/**
	*	Return the service type being offered - such as SQL.
	*
	*	@return	a service type
	*/
	public String getServiceType();
    
    /**
     *  Return a list of server types for this service
     * 
     *  @return -   a list of servers, the map is <name, properties>
     */
    public Map<String, Properties> getServers();

	/**
	*	Check this service is available, for instance, is a Database server running?
	*
	*	@param	prefs	the values used to connect to the database.  See individual Trugs for details.
    *                   N.B. The Preferences node passed is the sub-node for this specific Trug.
	*
	*	@return	true if this service is available, else false
	*
	*	@throws	GNDBException	if any of the connection parameters specified is invalid
	*/
	public boolean isAvailable(Preferences prefs) throws GNDBException;

	/**
	*	Perform any necessary closedown procedures, for instance, close database connexions.
	*/
	public void close();
    
    /**
     *  A method to check if the current database is empty
     * 
     *  @return true if the database is empty
     * 
     *  @since  2.8.1
     */
    public boolean isDatabaseEmpty() throws GNDBException;

	/**
	*	Retrieve a lister for ProductCategory items.
    * 
     * @return  a ProductCategoryLister
	*/
	public IProductCategoryLister getProductCategoryLister();
	/**
	*	Retrieve a builder for a new ProductCategory item.
    * 
     * @return  a ProductCategoryBuilder
	*/
	public IProductCategoryBuilder getProductCategoryBuilder();
	/**
	*	Retrieve a builder to update or delete a ProductCategory item.
	*
	*	@param	item	the item to be modified
     * @return  a ProductCategoryBuilder
	*/
	public IProductCategoryBuilder getProductCategoryBuilder(IProductCategory item);

	/**
	*	Retrieve a lister for ShoppingList items.
     * @return  a ShoppingListLister 
	*/
	public IShoppingListLister getShoppingListLister();
	/**
	*	Retrieve a builder for a new ShoppingList item.
     * @return  a ShoppingListBuilder 
	*/
	public IShoppingListBuilder getShoppingListBuilder();
	/**
	*	Retrieve a builder to update or delete a ShoppingList item.
	*
	*	@param	item	the item to be modified
     * @return  a ShoppingListBuilder 
	*/
	public IShoppingListBuilder getShoppingListBuilder(IShoppingList item);

	/**
	*	Retrieve a lister for PurchaseItem items.
     * @return  a PurchaseItemLister
	*/
	public IPurchaseItemLister getPurchaseItemLister();
	/**
	*	Retrieve a builder for a new PurchaseItem item.
     * @return  a PurchaseItemBuilder
	*/
	public IPurchaseItemBuilder getPurchaseItemBuilder();
	/**
	*	Retrieve a builder to update or delete a PurchaseItem item.
	*
	*	@param	item	the item to be modified
     * @return  a PurchaseItemBuilder 
	*/
	public IPurchaseItemBuilder getPurchaseItemBuilder(IPurchaseItem item);

	/**
	*	Retrieve a lister for WildlifeSpecies items.
     * @return 
	*/
	public IWildlifeSpeciesLister getWildlifeSpeciesLister();
	/**
	*	Retrieve a builder for a new WildlifeSpecies item.
     * @return  a WildlifeSpeciesLister 
	*/
	public IWildlifeSpeciesBuilder getWildlifeSpeciesBuilder();
	/**
	*	Retrieve a builder to update or delete a WildlifeSpecies item.
	*
	*	@param	item	the item to be modified
     * @return  a WildlifeSpeciesBuilder
	*/
	public IWildlifeSpeciesBuilder getWildlifeSpeciesBuilder(IWildlifeSpecies item);

	/**
	*	Retrieve a lister for GroundworkActivity items.
     * @return  a GroundworkActivityLister
	*/
	public IGroundworkActivityLister getGroundworkActivityLister();
	/**
	*	Retrieve a builder for a new GroundworkActivity item.
     * @return  a GroundworkActivityBuilder
	*/
	public IGroundworkActivityBuilder getGroundworkActivityBuilder();
	/**
	*	Retrieve a builder to update or delete a GroundworkActivity item.
	*
	*	@param	item	the item to be modified
     * @return  a GroundworkActivityBuilder
	*/
	public IGroundworkActivityBuilder getGroundworkActivityBuilder(IGroundworkActivity item);

	/**
	*	Retrieve a lister for Groundwork items.
     * @return  a GroundworkLister
	*/
	public IGroundworkLister getGroundworkLister();
	/**
	*	Retrieve a builder for a new Groundwork item.
     * @return  a GroundworkBuilder
	*/
	public IGroundworkBuilder getGroundworkBuilder();
	/**
	*	Retrieve a builder to update or delete a Groundwork item.
	*
	*	@param	item	the item to be modified
     * @return  a GroundworkBuilder
	*/
	public IGroundworkBuilder getGroundworkBuilder(IGroundwork item);

	/**
	*	Retrieve a lister for AfflictionClass items.
     * @return 
	*/
	public IAfflictionClassLister getAfflictionClassLister();
	/**
	*	Retrieve a builder for a new AfflictionClass item.
     * @return 
	*/
	public IAfflictionClassBuilder getAfflictionClassBuilder();
	/**
	*	Retrieve a builder to update or delete a AfflictionClass item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IAfflictionClassBuilder getAfflictionClassBuilder(IAfflictionClass item);

	/**
	*	Retrieve a lister for Weather items.
     * @return 
	*/
	public IWeatherLister getWeatherLister();
	/**
	*	Retrieve a builder for a new Weather item.
     * @return 
     * @return  
	*/
	public IWeatherBuilder getWeatherBuilder();
	/**
	*	Retrieve a builder to update or delete a Weather item.
	*
	*	@param	item	the item to be modified
	*/
	public IWeatherBuilder getWeatherBuilder(IWeather item);

	/**
	*	Retrieve a lister for RetailerHasProduct items.
     * @return 
     * @return  
	*/
	public IRetailerHasProductLister getRetailerHasProductLister();
	/**
	*	Retrieve a builder for a new RetailerHasProduct item.
	*/
	public IRetailerHasProductBuilder getRetailerHasProductBuilder();
	/**
	*	Retrieve a builder to update or delete a RetailerHasProduct item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IRetailerHasProductBuilder getRetailerHasProductBuilder(IRetailerHasProduct item);

	/**
	*	Retrieve a lister for ProductBrand items.
	*/
	public IProductBrandLister getProductBrandLister();
	/**
	*	Retrieve a builder for a new ProductBrand item.
     * @return 
	*/
	public IProductBrandBuilder getProductBrandBuilder();
	/**
	*	Retrieve a builder to update or delete a ProductBrand item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IProductBrandBuilder getProductBrandBuilder(IProductBrand item);

	/**
	*	Retrieve a lister for HusbandryClass items.
	*/
	public IHusbandryClassLister getHusbandryClassLister();
	/**
	*	Retrieve a builder for a new HusbandryClass item.
     * @return 
	*/
	public IHusbandryClassBuilder getHusbandryClassBuilder();
	/**
	*	Retrieve a builder to update or delete a HusbandryClass item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IHusbandryClassBuilder getHusbandryClassBuilder(IHusbandryClass item);

	/**
	*	Retrieve a lister for Affliction items.
     * @return 
	*/
	public IAfflictionLister getAfflictionLister();
	/**
	*	Retrieve a builder for a new Affliction item.
     * @return 
	*/
	public IAfflictionBuilder getAfflictionBuilder();
	/**
	*	Retrieve a builder to update or delete a Affliction item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IAfflictionBuilder getAfflictionBuilder(IAffliction item);

	/**
	*	Retrieve a lister for Wildlife items.
     * @return 
	*/
	public IWildlifeLister getWildlifeLister();
	/**
	*	Retrieve a builder for a new Wildlife item.
     * @return 
	*/
	public IWildlifeBuilder getWildlifeBuilder();
	/**
	*	Retrieve a builder to update or delete a Wildlife item.
	*
	*	@param	item	the item to be modified
     * @return 
     * @return  
	*/
	public IWildlifeBuilder getWildlifeBuilder(IWildlife item);

	/**
	*	Retrieve a lister for Product items.
     * @return 
	*/
	public IProductLister getProductLister();
	/**
	*	Retrieve a builder for a new Product item.
	*/
	public IProductBuilder getProductBuilder();
	/**
	*	Retrieve a builder to update or delete a Product item.
	*
	*	@param	item	the item to be modified
	*/
	public IProductBuilder getProductBuilder(IProduct item);

	/**
	*	Retrieve a lister for Reminder items.
     * @return 
	*/
	public IReminderLister getReminderLister();
	/**
	*	Retrieve a builder for a new Reminder item.
     * @return 
	*/
	public IReminderBuilder getReminderBuilder();
	/**
	*	Retrieve a builder to update or delete a Reminder item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IReminderBuilder getReminderBuilder(IReminder item);

	/**
	*	Retrieve a lister for Retailer items.
     * @return 
     * @return  
	*/
	public IRetailerLister getRetailerLister();
	/**
	*	Retrieve a builder for a new Retailer item.
     * @return 
	*/
	public IRetailerBuilder getRetailerBuilder();
	/**
	*	Retrieve a builder to update or delete a Retailer item.
	*
	*	@param	item	the item to be modified
	*/
	public IRetailerBuilder getRetailerBuilder(IRetailer item);

	/**
	*	Retrieve a lister for Purchase items.
	*/
	public IPurchaseLister getPurchaseLister();
	/**
	*	Retrieve a builder for a new Purchase item.
	*/
	public IPurchaseBuilder getPurchaseBuilder();
	/**
	*	Retrieve a builder to update or delete a Purchase item.
	*
	*	@param	item	the item to be modified
	*/
	public IPurchaseBuilder getPurchaseBuilder(IPurchase item);

	/**
	*	Retrieve a lister for PlantVariety items.
     * @return 
     * @return  
	*/
	public IPlantVarietyLister getPlantVarietyLister();
	/**
	*	Retrieve a builder for a new PlantVariety item.
     * @return 
	*/
	public IPlantVarietyBuilder getPlantVarietyBuilder();
	/**
	*	Retrieve a builder to update or delete a PlantVariety item.
	*
	*	@param	item	the item to be modified
	*/
	public IPlantVarietyBuilder getPlantVarietyBuilder(IPlantVariety item);
	/**
	*	Retrieve a builder for a new PlantVariety item for the given PlantSpecies.
	*
	*	@param	species	the parent species
	*/
	public IPlantVarietyBuilder getPlantVarietyBuilder(IPlantSpecies species);
	/**
	*	Retrieve a builder for a new PlantVariety item for the given PlantSpecies.
	*
	*	@param	species	the parent species
	*	@param	item	the item to be modified
	*/
	public IPlantVarietyBuilder getPlantVarietyBuilder(IPlantSpecies species, IPlantVariety item);

	/**
	*	Retrieve a lister for AfflictionEvent items.
	*/
	public IAfflictionEventLister getAfflictionEventLister();
	/**
	*	Retrieve a builder for a new AfflictionEvent item.
	*/
	public IAfflictionEventBuilder getAfflictionEventBuilder();
	/**
	*	Retrieve a builder to update or delete a AfflictionEvent item.
	*
	*	@param	item	the item to be modified
	*/
	public IAfflictionEventBuilder getAfflictionEventBuilder(IAfflictionEvent item);

	/**
	*	Retrieve a lister for PlantNote items.
     * @return 
	*/
	public IPlantNoteLister getPlantNoteLister();
	/**
	*	Retrieve a builder for a new PlantNote item.
     * @return 
	*/
	public IPlantNoteBuilder getPlantNoteBuilder();
	/**
	*	Retrieve a builder to update or delete a PlantNote item.
	*
	*	@param	item	the item to be modified
	*/
	public IPlantNoteBuilder getPlantNoteBuilder(IPlantNote item);

	/**
	*	Retrieve a lister for Husbandry items.
     * @return 
	*/
	public IHusbandryLister getHusbandryLister();
	/**
	*	Retrieve a builder for a new Husbandry item.
     * @return 
	*/
	public IHusbandryBuilder getHusbandryBuilder();
	/**
	*	Retrieve a builder to update or delete a Husbandry item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IHusbandryBuilder getHusbandryBuilder(IHusbandry item);

	/**
	*	Retrieve a lister for ToDoList items.
     * @return 
	*/
	public IToDoListLister getToDoListLister();
	/**
	*	Retrieve a builder for a new ToDoList item.
     * @return 
	*/
	public IToDoListBuilder getToDoListBuilder();
	/**
	*	Retrieve a builder to update or delete a ToDoList item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IToDoListBuilder getToDoListBuilder(IToDoList item);

	/**
	*	Retrieve a lister for WeatherCondition items.
     * @return 
	*/
	public IWeatherConditionLister getWeatherConditionLister();
	/**
	*	Retrieve a builder for a new WeatherCondition item.
     * @return 
	*/
	public IWeatherConditionBuilder getWeatherConditionBuilder();
	/**
	*	Retrieve a builder to update or delete a WeatherCondition item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IWeatherConditionBuilder getWeatherConditionBuilder(IWeatherCondition item);

	/**
	*	Retrieve a lister for PlantSpecies items.
	*/
	public IPlantSpeciesLister getPlantSpeciesLister();
	/**
	*	Retrieve a builder for a new PlantSpecies item.
     * @return 
	*/
	public IPlantSpeciesBuilder getPlantSpeciesBuilder();
	/**
	*	Retrieve a builder to update or delete a PlantSpecies item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public IPlantSpeciesBuilder getPlantSpeciesBuilder(IPlantSpecies item);

	/**
	*	Retrieve a lister for Sale items.
     * @return 
	*/
	public ISaleLister getSaleLister();
	/**
	*	Retrieve a builder for a new Sale item.
     * @return 
	*/
	public ISaleBuilder getSaleBuilder();
	/**
	*	Retrieve a builder to update or delete a Sale item.
	*
	*	@param	item	the item to be modified
     * @return 
	*/
	public ISaleBuilder getSaleBuilder(ISale item);

	/**
	*	Retrieve a lister for SaleItem items.
	*/
	public ISaleItemLister getSaleItemLister();
	/**
	*	Retrieve a builder for a new SaleItem item.
     * @return 
	*/
	public ISaleItemBuilder getSaleItemBuilder();
	/**
	*	Retrieve a builder to update or delete a SaleItem item.
	*
	*	@param	item	the item to be modified
	*/
	public ISaleItemBuilder getSaleItemBuilder(ISaleItem item);

	/**
	 *	Retrieve a lister for Location.
	 * @return	the lister
	 *
	 * @since 3.0.0
	 */
	public ILocationLister getLocationLister();
	/**
	 *	Retrieve a builder for a new Location.
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public ILocationBuilder getLocationBuilder();
	/**
	 *	Retrieve a builder to update or delete a Location.
	 *
	 *	@param	item	the item to be modified
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public ILocationBuilder getLocationBuilder(ILocation item);

	/**
	 *	Retrieve a lister for Journal.
	 * @return	the lister
	 *
	 * @since 3.0.0
	 */
	public IJournalLister getJournalLister();
	/**
	 *	Retrieve a builder for a new Journal.
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public IJournalBuilder getJournalBuilder();
	/**
	 *	Retrieve a builder to update or delete a Journal.
	 *
	 *	@param	item	the item to be modified
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public IJournalBuilder getJournalBuilder(IJournal item);

	/**
	 *	Retrieve a lister for Review.
	 * @return	the lister
	 *
	 * @since 3.0.0
	 */
	public IReviewLister getReviewLister();
	/**
	 *	Retrieve a builder for a new Review.
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public IReviewBuilder getReviewBuilder();
	/**
	 *	Retrieve a builder to update or delete a Review.
	 *
	 *	@param	item	the item to be modified
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public IReviewBuilder getReviewBuilder(IReview item);

	/**
	 *	Retrieve a lister for CropRotationGroup.
	 * @return	the lister
	 *
	 * @since 3.0.0
	 */
	public ICropRotationGroupLister getCropRotationGroupLister();
	/**
	 *	Retrieve a builder for a new CropRotationGroup.
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public ICropRotationGroupBuilder getCropRotationGroupBuilder();
	/**
	 *	Retrieve a builder to update or delete a CropRotationGroup.
	 *
	 *	@param	item	the item to be modified
	 * @return	the builder
	 *
	 * @since 3.0.0
	 */
	public ICropRotationGroupBuilder getCropRotationGroupBuilder(ICropRotationGroup item);

	public ICroppingPlanLister getCroppingPlanLister();
	public ICroppingPlanBuilder getCroppingPlanBuilder();
	public ICroppingPlanBuilder getCroppingPlanBuilder(ICroppingPlan item);

	public ICroppingActualLister getCroppingActualLister();
	public ICroppingActualBuilder getCroppingActualBuilder();
	public ICroppingActualBuilder getCroppingActualBuilder(ICroppingActual item);

	ILifecycleAnalysisLister getLifecycleAnalysisLister();

	/**
	*	Dumps the entire database as a set of JSON files.
	*
	*	@param	prefs	Used to retrieve the JSON dump directory
	*
	*	@throws	java.io.IOException	if the value of JSONDumpDir in prefs is NOT a directory and cannot be created
	*	@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 toJson(Preferences prefs) throws IOException, GNDBException;
	/**
	*	Updates the database from a (set of) JSON files.
	*
	*	@param	prefs	Used to retrieve the JSON dump directory
	*
	*	@throws	java.io.IOException	if the value of JSONDumpDir in prefs is NOT a directory
	*	@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 fromJson(Preferences prefs) throws IOException, GNDBException;
}
