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

/*
	Change log
	2.6.1   Code tidy-up
    2.9.6	When a Diary entry is added/changed, make sure updated comments are shown
    3.0.1	Allow direct creation of new entries in the catalogue list
    3.0.4	Use new convenience class NotebookBeanDeleter for deletion.
    		Set first row of catalogue selected.
 */

package uk.co.gardennotebook;

import javafx.application.Platform;
import uk.co.gardennotebook.fxbean.ProductBrandBean;

import java.util.List;
//import java.util.Optional;
import java.io.IOException;
import java.util.ResourceBundle;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.stage.WindowEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.text.Text;
import javafx.scene.Node;
//import javafx.scene.control.Alert;
//import javafx.scene.control.ButtonType;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.EntryMessage;
//import uk.co.gardennotebook.fxbean.RetailerBean;
import uk.co.gardennotebook.spi.GNDBException;

/**
	*	Controller class for create/update of ProductBrand catalogue
	*
	*	@author Andy Gegg
	*	@version	3.0.4
	*	@since	1.0
 */
public class ProductBrandCat extends AnchorPane implements INotebookLoadable
{

	private static final Logger LOGGER = LogManager.getLogger();

	@FXML
	private ResourceBundle resources;

	@FXML
	private TableView<ProductBrandBean> tblCatalogue;
	@FXML
	private TableColumn<ProductBrandBean, String> colName;
	@FXML
	private TableColumn<ProductBrandBean, ProductBrandBean> colRetailer;
	@FXML
	private TableColumn<ProductBrandBean, String> colDescription;
	@FXML
	private TableColumn<ProductBrandBean, ProductBrandBean> colComment;
	@FXML
	private Button btnChange;
	@FXML
	private Button btnDelete;

	@FXML
	private MenuItem ctxmnuDelete;

	private Consumer<Node> loadSplit;
	private Consumer<Node> clearSplit;
	private BiConsumer<String, Node> loadTab;
	private Consumer<Node> clearTab;

	ProductBrandCat()
	{
		FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/ProductBrandCat.fxml"),
			ResourceBundle.getBundle("notebook") );
		fxmlLoader.setRoot(this);
		fxmlLoader.setController(this);
		try {
			fxmlLoader.load();	// NB initialize is called from in here
		} catch (IOException exception) {
			throw new RuntimeException(exception);
		}
	}// constructor

	/*
	* Initializes the controller class.
	*/
	@FXML
	private void initialize()
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("initialize()");
		List<ProductBrandBean> items = FXCollections.emptyObservableList();
		try {
			items = ProductBrandBean.fetchAll();
		} catch (GNDBException ex) {
			PanicHandler.panic(ex);
		}
		tblCatalogue.setColumnResizePolicy(NotebookResizer.using(tblCatalogue));
		colName.setCellFactory(TextFieldTableCell.forTableColumn());
		colName.setCellValueFactory(cdf -> cdf.getValue().nameProperty());
		colRetailer.setCellValueFactory(cdf -> new SimpleObjectProperty<>(cdf.getValue()));
		colRetailer.setCellFactory(x -> new TableCell<>()
		{
			@Override
			protected void updateItem(ProductBrandBean item, boolean empty)
			{
				super.updateItem(item, empty);
				if (empty || item == null)
				{
					setGraphic(null);
					setText(null);
					return;
				}
				updateViewMode();
			}

			@Override
			public void startEdit()
			{
				super.startEdit();
				updateViewMode();
			}

			@Override
			public void cancelEdit()
			{
				super.cancelEdit();
				updateViewMode();
			}

			private void updateViewMode()
			{
				LOGGER.debug("retailer: updateViewMode(): item: {}", getItem());
				setGraphic(null);
				setText(null);
				if (getItem() == null)
					return;

				if (isEditing())
				{
					VBox vBox = new VBox();
					RetailerCombo cb = new RetailerCombo(getItem().getRetailer());
					cb.setEditable(true);
//					cb.setMandatory(true);	//	3.0.1	If mandatory the user can't clear the Retailer field - but can in the Editor
					cb.setOnAction(ev -> {
						LOGGER.debug("retailer: setOnAction: selection: {}", cb.getSelectionModel().getSelectedItem());
						getItem().setRetailer(cb.getSelectionModel().getSelectedItem());
						commitEdit(getItem());
					});
					vBox.getChildren().add(cb);
					setGraphic(vBox);
				}
				else
				{
					if (getItem() != null && getItem().getRetailer() != null)
					{
						setText(getItem().getRetailer().getName());
					}
				}

			}
		});

		colDescription.setCellFactory(TextFieldTableCell.forTableColumn());
		colDescription.setCellValueFactory(cdf -> cdf.getValue().descriptionProperty());
		colComment.setCellValueFactory((e)-> new SimpleObjectProperty<>( e.getValue()));
		colComment.setCellFactory(x -> new EditorCommentTableCell<>(resources));	//	2.9.6

		//	3.0.1
		tblCatalogue.getSortOrder().add(colName);
		//	set a Comparator so that the 'null' row is still last after adding an item - which re-sorts the list
		colName.setComparator((s1, s2)->{
			if (s1==null || s1.isBlank()) return 1;
			if (s2==null || s2.isBlank()) return -1;
			return s1.compareTo(s2);
		});

		tblCatalogue.getItems().setAll(items);

		//	3.0.1
		CatalogueNotebookBeanAdder<ProductBrandBean> catAdder = new CatalogueNotebookBeanAdder<>(tblCatalogue, ProductBrandBean::new, ProductBrandBean::nameProperty);
		ProductBrandBean cb_new = new ProductBrandBean();
		cb_new.nameProperty().addListener(catAdder);
		tblCatalogue.getItems().add(cb_new);

		// only allow change and delete if there is a row selected
		btnChange.disableProperty().bind(tblCatalogue.getSelectionModel().selectedItemProperty().isNull());
		btnDelete.setDisable(true);
		tblCatalogue.getSelectionModel().selectedItemProperty().addListener((obs, old, nval) ->{
			try {
				btnDelete.setDisable( (nval == null) || !(nval.canDelete()) );
			} catch (GNDBException ex) {
				PanicHandler.panic(ex);
			}
				});

		tblCatalogue.getSelectionModel().select(0);
		Platform.runLater(() -> tblCatalogue.requestFocus());	//	this enables keyboard navigation with the up/down arrows

		if (!items.isEmpty() && items.size() < 50)
		{
			double nameWidth = new Text(colName.getText()).getLayoutBounds().getWidth() + 12;
			for (ProductBrandBean b : items)
			{
				final Text t = new Text(b.getName());
				final double wid = t.getLayoutBounds().getWidth();
				if (wid > nameWidth) nameWidth = wid;
			}
			colName.setPrefWidth(nameWidth+10);
		}

		LOGGER.traceExit(log4jEntryMsg);
	}	//	initialize()

	@Override
	public void setLoadSplit(Consumer<Node> code)
	{
		loadSplit = code;
	}

	@Override
	public void setClearSplit(Consumer<Node> code)
	{
		clearSplit = code;
	}

	@Override
	public void setLoadTab(BiConsumer<String, Node> code)
	{
		loadTab = code;
	}

	@Override
	public void setClearTab(Consumer<Node> code)
	{
		clearTab = code;
	}

	@FXML
	private void ctxmnuOnShowing(WindowEvent event)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("ctxmnuOnShowing()");
		ProductBrandBean ixBean = tblCatalogue.getSelectionModel().selectedItemProperty().get();
		try {
			ctxmnuDelete.setDisable( (ixBean == null) || !(ixBean.canDelete()) );
		} catch (GNDBException ex) {
			PanicHandler.panic(ex);
		}
		LOGGER.traceExit(log4jEntryMsg);
	}	//	ctxmnuOnShowing()

	@FXML
	private void btnAddOnAction(ActionEvent event)
	{
		ctxmnuAddOnAction(event);
	}

	@FXML
	private void btnChangeOnAction(ActionEvent event)
	{
		ctxmnuChangeOnAction(event);
	}

	@FXML
	private void btnDeleteOnAction(ActionEvent event)
	{
		ctxmnuDeleteOnAction(event);
	}

	@FXML
	private void ctxmnuAddOnAction(ActionEvent event)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("ctxmnuAddOnAction()");
		ProductBrandEditor tabCon = new ProductBrandEditor();
		loadTab.accept(resources.getString("tab.productbrand"), tabCon);
		tabCon.newBeanProperty().addListener((obs, oldVal, newVal) -> {
			tblCatalogue.getItems().add(newVal);
			tblCatalogue.sort();	//	3.0.1
		});
		LOGGER.traceExit(log4jEntryMsg);
	}	//	ctxmnuAddOnAction()

	@FXML
	private void ctxmnuChangeOnAction(ActionEvent event)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("ctxmnuChangeOnAction()");
		ProductBrandBean ixBean = tblCatalogue.getSelectionModel().selectedItemProperty().get();
		if (ixBean == null)
		{
			LOGGER.debug("thisValueBean is null");
			LOGGER.traceExit(log4jEntryMsg);
			return;
		}

		ProductBrandEditor tabCon = new ProductBrandEditor(ixBean);
		loadTab.accept(resources.getString("tab.productbrand"), tabCon);
		tabCon.deletedBeanProperty().addListener((obs, oldVal, newVal) -> tblCatalogue.getItems().remove(ixBean));
		LOGGER.traceExit(log4jEntryMsg);
	}	//	ctxmnuChangeOnAction()

	@FXML
	private void ctxmnuDeleteOnAction(ActionEvent event)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("ctxmnuDeleteOnAction()");
		ProductBrandBean ixBean = tblCatalogue.getSelectionModel().selectedItemProperty().get();
		if (ixBean == null)
		{
			LOGGER.debug("thisValueBean is null");
			LOGGER.traceExit(log4jEntryMsg);
			return;
		}

//		boolean canDelete = false;
//		try {
//			canDelete = ixBean.canDelete();
//		} catch (GNDBException ex) {
//			PanicHandler.panic(ex);
//		}
//		if (!canDelete)
//		{
//			Alert checkDelete = new Alert(Alert.AlertType.INFORMATION, resources.getString("alert.cannotdelete"), ButtonType.OK);
//			Optional<ButtonType> result = checkDelete.showAndWait();
//			LOGGER.traceExit(log4jEntryMsg);
//			return;
//		}
//
//		Alert checkDelete = new Alert(Alert.AlertType.CONFIRMATION, resources.getString("alert.confirmdelete"), ButtonType.NO, ButtonType.YES);
//		Optional<ButtonType> result = checkDelete.showAndWait();
//		LOGGER.debug("after delete dialog: result:{}, result.get:{}",result, result.get());
//		if (result.isPresent() && result.get() == ButtonType.YES)
//		{
//			LOGGER.debug("after delete confirmed");
//			try {
//				ixBean.delete();
//			} catch (GNDBException ex) {
//				PanicHandler.panic(ex);
//			}
//			tblCatalogue.getItems().remove(ixBean);
//		}
		NotebookBeanDeleter<ProductBrandBean> deleterImpl = new NotebookBeanDeleter<>(resources);
		if (deleterImpl.deleteItemImpl(ixBean))
		{
			tblCatalogue.getItems().remove(ixBean);
		}

		LOGGER.traceExit(log4jEntryMsg);
	}	//	ctxmnuDeleteOnAction()


}

