package com.madeorsk.smartnotes.notes;

import java.io.File;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import com.madeorsk.smartnotes.ListBox;
import com.madeorsk.smartnotes.NoteColorSelector;
import com.madeorsk.smartnotes.NotesExplorer;
import com.madeorsk.smartnotes.SavesManager;
import com.madeorsk.smartnotes.SmartNotes;
import com.madeorsk.smartnotes.TypeSelector;
import com.madeorsk.smartnotes.Utils;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

public class ListNote extends Note
{
	private ListBox listBox;
	private boolean loading = false;

	public ListNote()
	{
		this.setName("Text_" + Calendar.getInstance().get(Calendar.YEAR) + "." + Calendar.getInstance().get(Calendar.MONTH) + "." + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + "-" + Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE));
		this.listBox = new ListBox(false);
	}

	@Override
	public VBox getViewBox(final NotesExplorer explorer)
	{
		Map<String, Boolean> listBoxMap = this.listBox.getList();
		this.listBox = new ListBox(false);
		this.listBox.updateList(listBoxMap);
		VBox box = new VBox();
		box.setFillWidth(true);

		final Label nameField = new Label();

		HBox titleBox = new HBox();
		{
			titleBox.setPadding(new Insets(10, 0, 0, 0));

			VBox returnButton = new VBox();
			returnButton.setId("imageButton");
			returnButton.setCursor(Cursor.HAND);
			returnButton.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/ReturnIcon.png")));
			returnButton.setOnMouseClicked((MouseEvent event) -> {
				explorer.updateCurrentFolder();
				SmartNotes.instance.setContent(explorer, true);
			});
			titleBox.getChildren().add(returnButton);

			VBox editButton = new VBox();
			editButton.setId("imageButton");
			editButton.setCursor(Cursor.HAND);
			editButton.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/EditIcon.png")));
			editButton.setOnMouseClicked((MouseEvent event) -> {
				SmartNotes.instance.setContent(ListNote.this.getEditBox(explorer));
			});
			HBox buttonsBox = new HBox();
			buttonsBox.getChildren().add(editButton);
			buttonsBox.prefWidthProperty().bind(titleBox.widthProperty().subtract(returnButton.widthProperty()).divide(2));
			titleBox.getChildren().add(buttonsBox);

			NoteColorSelector colorSelector = new NoteColorSelector();
			colorSelector.setAlignment(Pos.CENTER);
			colorSelector.prefWidthProperty().bind(titleBox.widthProperty().subtract(returnButton.widthProperty()).divide(2));
			colorSelector.addColor(NoteColor.WHITE);
			colorSelector.addColor(NoteColor.BLUE);
			colorSelector.addColor(NoteColor.YELLOW);
			colorSelector.addColor(NoteColor.RED);
			colorSelector.addColor(NoteColor.GREEN);
			colorSelector.setSelectedColor(this.getNoteColor());
			colorSelector.selectedColorProperty().addListener((ObservableValue<? extends NoteColor> ov, NoteColor oldValue, NoteColor newValue) -> {
				ListNote.this.setNoteColor(newValue);
				nameField.setStyle("-fx-text-fill: rgb(" + newValue.getColor().getRed() * 255 + "," + newValue.getColor().getGreen() * 255 + "," + newValue.getColor().getBlue() * 255 + ");");
				explorer.requestSave(ListNote.this);
			});
			titleBox.getChildren().add(colorSelector);
		}
		box.getChildren().add(titleBox);

		// NAME FIELD
		{
			nameField.prefWidthProperty().bind(box.widthProperty());
			nameField.setAlignment(Pos.CENTER);
			nameField.setId("nameField");
			nameField.setStyle("-fx-text-fill: rgb(" + this.getNoteColor().getColor().getRed() * 255 + "," + this.getNoteColor().getColor().getGreen() * 255 + "," + this.getNoteColor().getColor().getBlue() * 255 + ");");
			nameField.setText(this.getName());
			nameField.textProperty().addListener((ObservableValue<? extends String> ov, String oldValue, String newValue) -> {
				ListNote.this.setName(newValue);
				explorer.requestSave(ListNote.this);
			});
		}
		box.getChildren().add(nameField);

		HBox separator = new HBox();
		separator.setId("separator");
		separator.setPrefHeight(5);

		SmartNotes.webView.getEngine().loadContent(Utils.markdownToHtml(this.getTextContent()));
		SmartNotes.webView.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty()).subtract(separator.heightProperty()).divide(2));
		box.getChildren().add(SmartNotes.webView);

		box.getChildren().add(separator);

		this.listBox.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty()).subtract(separator.heightProperty()).divide(2));
		this.listBox.setListChangeListener(() -> {
			if (!ListNote.this.loading)
				explorer.requestSave(ListNote.this);
		});
		box.getChildren().add(this.listBox);

		return box;
	}

	@Override
	public VBox getEditBox(final NotesExplorer explorer)
	{
		Map<String, Boolean> listBoxMap = this.listBox.getList();
		this.listBox = new ListBox(true);
		this.listBox.updateList(listBoxMap);
		VBox box = new VBox();
		box.setFillWidth(true);

		final TextField nameField = new TextField();

		HBox titleBox = new HBox();
		{
			titleBox.setPadding(new Insets(10, 0, 0, 0));

			VBox returnButton = new VBox();
			returnButton.setId("imageButton");
			returnButton.setCursor(Cursor.HAND);
			returnButton.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/ReturnIcon.png")));
			returnButton.setOnMouseClicked((MouseEvent event) -> {
				explorer.updateCurrentFolder();
				SmartNotes.instance.setContent(explorer, true);
			});
			titleBox.getChildren().add(returnButton);

			TypeSelector typeSelector = new TypeSelector(explorer, this);
			typeSelector.setAlignment(Pos.CENTER);
			typeSelector.prefWidthProperty().bind(titleBox.widthProperty().subtract(returnButton.widthProperty()).divide(2));
			titleBox.getChildren().add(typeSelector);

			NoteColorSelector colorSelector = new NoteColorSelector();
			colorSelector.setAlignment(Pos.CENTER);
			colorSelector.prefWidthProperty().bind(titleBox.widthProperty().subtract(returnButton.widthProperty()).divide(2));
			colorSelector.addColor(NoteColor.WHITE);
			colorSelector.addColor(NoteColor.BLUE);
			colorSelector.addColor(NoteColor.YELLOW);
			colorSelector.addColor(NoteColor.RED);
			colorSelector.addColor(NoteColor.GREEN);
			colorSelector.setSelectedColor(this.getNoteColor());
			colorSelector.selectedColorProperty().addListener((ObservableValue<? extends NoteColor> ov, NoteColor oldValue, NoteColor newValue) -> {
				ListNote.this.setNoteColor(newValue);
				nameField.setStyle("-fx-text-fill: rgb(" + newValue.getColor().getRed() * 255 + "," + newValue.getColor().getGreen() * 255 + "," + newValue.getColor().getBlue() * 255 + ");");
				explorer.requestSave(ListNote.this);
			});
			titleBox.getChildren().add(colorSelector);
		}
		box.getChildren().add(titleBox);

		// NAME FIELD
		{
			nameField.setAlignment(Pos.CENTER);
			nameField.setId("nameField");
			nameField.setStyle("-fx-text-fill: rgb(" + this.getNoteColor().getColor().getRed() * 255 + "," + this.getNoteColor().getColor().getGreen() * 255 + "," + this.getNoteColor().getColor().getBlue() * 255 + ");");
			nameField.setText(this.getName());
			nameField.textProperty().addListener((ObservableValue<? extends String> ov, String oldValue, String newValue) -> {
				ListNote.this.setName(newValue);
				explorer.requestSave(ListNote.this);
			});
		}
		box.getChildren().add(nameField);

		//

		HBox separator = new HBox();
		separator.setId("separator");
		separator.setPrefHeight(5);

		final TextArea textArea = new TextArea();
		{
			textArea.setId("text");
			textArea.setWrapText(true);
			textArea.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty()).subtract(separator.heightProperty()).divide(2));
			textArea.setText(this.getTextContent());
			textArea.textProperty().addListener((ObservableValue<? extends String> ov, String oldValue, String newValue) -> {
				ListNote.this.setTextContent(newValue);
				explorer.requestSave(ListNote.this);
			});
			Platform.runLater(() -> {
				textArea.requestFocus();
				textArea.positionCaret(textArea.getLength());
			});
		}
		box.getChildren().add(textArea);

		box.getChildren().add(separator);

		this.listBox.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty()).subtract(separator.heightProperty()).divide(2));
		this.listBox.setListChangeListener(() -> {
			if (!ListNote.this.loading)
				explorer.requestSave(ListNote.this);
		});
		box.getChildren().add(this.listBox);

		return box;
	}

	@Override
	public void save(SavesManager saves, int id)
	{
		String fileContent = this.getName() + "\n" + this.getNoteColor().name() + "\n";
		Map<String, Boolean> list = this.listBox.getList();
		fileContent += Integer.toUnsignedString(list.keySet().size(), 16) + "\n";
		for (String key : list.keySet())
			fileContent += key + ":" + list.get(key).toString() + "\n";
		saves.writeFile(saves.getSaveFile(id), fileContent + this.getTextContent());
	}

	@Override
	public boolean load(SavesManager saves, int id)
	{
		if (saves.getSaveFile(id).exists())
		{
			this.loading = true;

			String saved = saves.readFile(saves.getSaveFile(id));

			int separatorIndex = saved.indexOf('\n');
			this.setName(saved.substring(0, separatorIndex));
			saved = saved.substring(separatorIndex + 1);

			separatorIndex = saved.indexOf('\n');
			this.setNoteColor(NoteColor.valueOf(saved.substring(0, separatorIndex)));
			saved = saved.substring(separatorIndex + 1);

			separatorIndex = saved.indexOf('\n');
			int listSize = Integer.parseUnsignedInt(saved.substring(0, separatorIndex), 16);
			Map<String, Boolean> list = new HashMap<String, Boolean>();
			for (int i = 0; i < listSize; i++)
			{
				saved = saved.substring(separatorIndex + 1);
				separatorIndex = saved.indexOf('\n');
				String listItemString = saved.substring(0, separatorIndex);
				int listItemSeparator = listItemString.lastIndexOf(':');
				list.put(listItemString.substring(0, listItemSeparator), Boolean.parseBoolean(listItemString.substring(listItemSeparator + 1)));
			}
			this.listBox.updateList(list);

			if (separatorIndex < saved.length() - 1)
				this.setTextContent(saved.substring(separatorIndex + 1));
			else
				this.setTextContent("");

			this.loading = false;
			return true;
		}
		else
			return false;
	}

	@Override
	public void delete(SavesManager saves, int id)
	{
		File saveFile = saves.getSaveFile(id);
		if (saveFile.exists())
			saveFile.delete();
	}
}
