/*
 * 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/>.
 */

/*
	Change log
	2.0.1   Remove calls to System.out.println
    2.3.0   Pick up tab-out from DatePicker
    2.4.0   Refactor TextTableCell out as EditorCommentTextTableCell for use elsewhere
    2.7.0   Use EditorCommentDateTableCell for consistency
            Fix bug where adding the first comment results in multiple copies being shown
                (this was down to using cancelEdit() instead of commitEdit() because
                  we don't know the type of object to return (an INotebookBean) while
                  trying to be clever and handle the first comment differently)
     2.9.6	When a Diary entry is added/changed, make sure updated comments are shown
     		Fix various bugs
	3.1.0	If you added a new first comment to a PI it didn't show up, here or in the Diary.  This is down to a
			sequencing problem - commitEdit() raises a Commit event and the handlers added in 2.9.6 execute first
			and the new comment only goes through addComment() afterwards.  The fix here is a bodge and really
			needs a better solution.  But it seems to work ok.
			Previous analysis is basically wrong - although the commit event does need handling.  A lot of, if not all of,
			the various 'vanishing first comment' bugs were down to a basic misunderstanding in updateViewMode(), for
			not-editing cells - the display must still be bound to the commentTextProperty of the parent bean.
*/
package uk.co.gardennotebook;

//import javafx.beans.binding.StringBinding;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.EntryMessage;
import uk.co.gardennotebook.fxbean.CommentBean;
import uk.co.gardennotebook.fxbean.INotebookBean;
import uk.co.gardennotebook.spi.GNDBException;
import uk.co.gardennotebook.spi.GNDBRuntimeException;

//import java.util.List;
import java.util.ResourceBundle;

/**
	*	Implements update-able Comment cells in tables
	*
	*	@author Andy Gegg
	*	@version	3.1.0
	*	@since 1.0
 */
final class CommentCellImpl
{

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

	private final ResourceBundle resources;

	private INotebookBean parent;

	CommentCellImpl(ResourceBundle res)
	{
		resources = res;
	}
	
	public void setParent(INotebookBean parent)
	{
		this.parent = parent;
	}
	
	public void updateViewMode(IndexedCell cell, ObservableList<CommentBean> comments)
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("updateViewMode(): comments: {}", comments);
        
		cell.setGraphic(null);
		cell.setText(null);
        
        if (comments == null)
        {
            LOGGER.debug("CommentCellImpl: updateViewMode: comments is null");
            throw new IllegalArgumentException("CommentCellImpl: updateViewMode: comments is null");
        }
        
		VBox vBox = new VBox();

		double cellHeight = 0;	// this is ok - the rest of the line contents will sort it out
		if (cell.isEditing())
		{
			LOGGER.debug("Editing: parent: {}", parent);
			TableView<CommentBean> ctab = new TableView<>();
			ctab.setEditable(true);

			TableColumn<CommentBean, CommentBean> dateCol = new TableColumn<>(resources.getString("col.comment.date"));
			dateCol.setCellValueFactory(cb -> new SimpleObjectProperty<>(cb.getValue()));
			dateCol.setCellFactory(c -> new EditorCommentDateTableCell(resources)); //  2.7.0

			TableColumn<CommentBean, String> textCol = new TableColumn<>(resources.getString("col.comment.text"));
			textCol.setCellValueFactory(cb -> cb.getValue().commentProperty());
			textCol.setCellFactory(c -> new EditorCommentTextTableCell(resources)); //  2.4.0

			ctab.getColumns().addAll(dateCol, textCol);

			ctab.setColumnResizePolicy(NotebookResizer.using(ctab));

			ctab.getItems().addAll(comments);
			if (parent != null)
			{
				ctab.getItems().add(new CommentBean(parent));
			}
			cellHeight = cell.fontProperty().get().getSize() * 2 * (comments.size() + 3);	// horrible bodge!

			//	2.9.6
			//	These event handlers are needed to handle 2 situations:
			//	- the table does not close when a comment has been edited, which is counterintuitive (what should I do next?)
			//		although being able to edit >1 comment might be considered useful;
			//	- when the table does NOT close, the underlying edit handler for the text column is working with the
			//		original set of CommentBeans so if a comment is added (creating a new bean) then edited in the
			//		still open table it passes the old bean back to the editor tab which doesn't know what to do with it
			//		in the non-explicitSave state and dumps.
			//	See ListView JavaDoc for details
			textCol.addEventHandler(TableColumn.editCommitEvent(), t -> cell.cancelEdit());
			dateCol.addEventHandler(TableColumn.editCommitEvent(), t -> cell.cancelEdit());

			MenuItem delMenuItem = new MenuItem(resources.getString("comment.btn.delete"));
			delMenuItem.setOnAction(e -> {
				LOGGER.debug("in Delete: event: {}", e);
				if (ctab.getSelectionModel().isEmpty()) return;
				LOGGER.debug("in Delete: selected item: {}", ctab.getSelectionModel().getSelectedItem());
				CommentBean selItem = ctab.getSelectionModel().getSelectedItem();
				if (selItem.get().isPresent())
				{
					try {
						parent.deleteComment(selItem);
					} catch (GNDBException ex) {
						throw new GNDBRuntimeException(ex);
					}
					ctab.getItems().remove(selItem);
					comments.remove(selItem);
					//	2.9.6
					//	close the edit after delete, or attempting to
					//	delete another comment throws an UnsupportedOperation exception
					cell.cancelEdit();	//	2.9.6
				}
			});
			ctab.setContextMenu(new ContextMenu(delMenuItem));

			cell.setPrefHeight(cellHeight);
			vBox.getChildren().add(ctab);
		}
		else
		{
//			LOGGER.debug("NOT editing");
//			if (comments != null  && comments.size() > 0)
//			{
				LOGGER.debug("updateViewMode(): not editing: parent: {}, commentTextProperty: {}", parent, parent.commentTextProperty().get());
				Text formattedText = new Text();
				formattedText.textProperty().bind(parent.commentTextProperty());
				formattedText.wrappingWidthProperty().bind(cell.widthProperty());
				vBox.getChildren().add(formattedText);
//			}
//			else
//			{// no comments, clear cell size from previous usage (cells are reused!) lest it was multiline
//				LOGGER.debug("CommentCellImpl: not editing: no comments");
//				Text formattedText = new Text();
//				formattedText.textProperty().bind(parent.commentTextProperty());
//				formattedText.wrappingWidthProperty().bind(cell.widthProperty());
//				vBox.getChildren().add(formattedText);
////				cell.setPrefHeight(0);
//			}
		}
		cell.setGraphic(vBox);
		LOGGER.traceExit(log4jEntryMsg);
	}


}
