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

/*
	WARNING
	Do not edit this file, it is generated.
 */

package uk.co.gardennotebook;

import java.io.IOException;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.text.Text;
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.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.GridPane;
import uk.co.gardennotebook.fxbean.CommentBean;
import uk.co.gardennotebook.spi.GNDBException;

import java.text.NumberFormat;

import uk.co.gardennotebook.fxbean.PurchaseItemBean;
import uk.co.gardennotebook.fxbean.PurchaseBean;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.EntryMessage;

/**
	*	Controller class for create/update of PurchaseItem items
	*
	*	@author Andy Gegg
	*	@version	1.1.0
	*	@since	1.0
 */
final public class PurchaseItemEditor extends GridPane implements INotebookLoadable
{

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

	private PurchaseBean parentBean;
	private final PurchaseItemBean thisValueBean;

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

	//	an observable property that the caller can monitor when a new item is being created
	private SimpleObjectProperty<PurchaseItemBean> newBean;
	private final boolean addingItem;

	//	an observable property that the caller can monitor when an item is deleted
	private SimpleObjectProperty<Object> deletedBean;

	private boolean addingBean;

	@FXML
	private ResourceBundle resources;

	@FXML
	private Button btnSave;
	@FXML
	private Button btnDelete;
	@FXML
	private ProductNameCombo cmbProductName;
	@FXML
	private TextField numQuantity;
	@FXML
	private TextField fldUnit;
	@FXML
	private TextField numItemCost;
	@FXML
	private TextField fldCurrency;

	@FXML
	private TableView<CommentBean> tbvComment;
	@FXML
	private TableColumn<CommentBean, CommentBean> tbvCommentDate;
	@FXML
	private TableColumn<CommentBean, String> tbvCommentText;

	//	handles addition of multiple comments
	private final ChangeListener<String> commentAdder = new ChangeListener<>() {
		@Override
		public void changed(ObservableValue obj, String oldVal, String newVal) {
			if ((newVal !=null) && !(newVal.isEmpty())) {
				CommentBean cb_extra = new CommentBean(PurchaseItemEditor.this.thisValueBean);
				cb_extra.commentProperty().addListener(this);
				tbvComment.getItems().add(cb_extra);
				obj.removeListener(commentAdder);
			}
		}
	};

	PurchaseItemEditor(PurchaseBean parent)
	{
		this(parent, null);
	}

	PurchaseItemEditor(PurchaseBean parent, PurchaseItemBean initialVal)
	{
		this.thisValueBean = (initialVal != null ? initialVal : new PurchaseItemBean());
		this.addingItem = (initialVal == null);
		this.parentBean = parent;
		this.thisValueBean.setPurchase(parentBean);
		FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/PurchaseItemEditor.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);
		}
	}

	/**
	*	Initialises the controller class.
	*/
	@FXML
	private void initialize()
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("initialize()");
		tbvCommentDate.setCellValueFactory(e-> new SimpleObjectProperty<>( e.getValue()));
		tbvCommentDate.setCellFactory(x -> new EditorCommentDateTableCell(resources));
		tbvCommentText.setCellValueFactory(e->e.getValue().commentProperty());
		tbvCommentText.setCellFactory(TextFieldTableCell.forTableColumn());
		tbvComment.setColumnResizePolicy(NotebookResizer.using(tbvComment));
		tbvComment.getItems().setAll(thisValueBean.getComments());
		CommentBean cb_new = new CommentBean(this.thisValueBean);
		cb_new.commentProperty().addListener(commentAdder);
		tbvComment.getItems().add(cb_new);
		CommentBean cb_one = tbvComment.getItems().get(0);
		Text t = new Text(cb_one.getDate().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)));
		double wid = t.getLayoutBounds().getWidth();
		tbvCommentDate.setPrefWidth(wid+10);
		thisValueBean.setSaveRequired(true);
		cmbProductName.valueProperty().bindBidirectional(thisValueBean.nameProperty());
		numQuantity.textProperty().bindBidirectional(thisValueBean.quantityProperty(), NumberFormat.getInstance());
		fldUnit.textProperty().bindBidirectional(thisValueBean.unitProperty());
		fldUnit.setTextFormatter(MaxLengthTextFormatter.getFormatter(255));
		numItemCost.textProperty().bindBidirectional(thisValueBean.itemCostProperty(), NumberFormat.getCurrencyInstance());
		fldCurrency.textProperty().bindBidirectional(thisValueBean.currencyProperty());
		fldCurrency.setTextFormatter(MaxLengthTextFormatter.getFormatter(3));
		btnSave.disableProperty().bind(cmbProductName.valueProperty().isNull());
		try
		{
			btnDelete.setDisable(addingItem || !(this.thisValueBean.canDelete()));
		} catch (GNDBException ex) {
			PanicHandler.panic(ex);
		}
		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;
	}

	@Override
	public void clearUpOnClose(Event e)
	{
		thisValueBean.cancelEdit();
	}

	@FXML
	private void btnCancelOnAction(ActionEvent event)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("btnCancelOnAction()");
		if (thisValueBean == null)
		{
			LOGGER.debug("thisValueBean is null");
			LOGGER.traceExit(log4jEntryMsg);
			return;
		}
		thisValueBean.cancelEdit();
		clearTab.accept(this);
		LOGGER.traceExit(log4jEntryMsg);
	}	//	btnCancelOnAction()

	@FXML
	private void btnDeleteOnAction(ActionEvent event)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("btnDeleteOnAction()");
		if (thisValueBean == null)
		{
			LOGGER.debug("thisValueBean is null");
			LOGGER.traceExit(log4jEntryMsg);
			return;
		}
		boolean canDelete = false;
		try
		{
			canDelete = thisValueBean.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.debug("item cannot be deleted");
			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
			{
				thisValueBean.delete();
			} catch (GNDBException ex) {
				PanicHandler.panic(ex);
			}
			deletedBeanProperty().setValue(new Object());
			clearTab.accept(this);
		}
		LOGGER.traceExit(log4jEntryMsg);
	}	//	btnDeleteOnAction()

	@FXML
	private void btnSaveOnAction(ActionEvent event)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("btnSaveOnAction()");
		if (thisValueBean == null)
		{
			LOGGER.debug("thisValueBean is null");
			LOGGER.traceExit(log4jEntryMsg);
			return;
		}
		try
		{
			thisValueBean.save();
		} catch (GNDBException ex) {
			PanicHandler.panic(ex);
		}
		newBeanProperty().setValue(thisValueBean);
		clearTab.accept(this);
		LOGGER.traceExit(log4jEntryMsg);
	}	//	btnSaveOnAction()

	SimpleObjectProperty<PurchaseItemBean> newBeanProperty()
	{
		if (newBean == null)
		{
			newBean = new SimpleObjectProperty<>();
		}
		return newBean;
	}

	SimpleObjectProperty<Object> deletedBeanProperty()
	{
		if (deletedBean == null)
		{
			deletedBean = new SimpleObjectProperty<>();
		}
		return deletedBean;
	}

}
