package com.madeorsk.smartnotes;

import java.util.Arrays;
import java.util.Map;

import com.madeorsk.smartnotes.notes.Note;
import com.madeorsk.smartnotes.notes.TextNote;
import com.madeorsk.smartnotes.paths.FolderPath;
import com.madeorsk.smartnotes.paths.NotePath;
import com.madeorsk.smartnotes.paths.Path;

import javafx.animation.FadeTransition;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Label;
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;
import javafx.util.Duration;

public class NotesExplorer extends VBox
{
	private SavesManager saves;
	private Map<Integer, Note> notes;

	private HBox titleBox;
	private FolderPath currentFolder;

	public NotesExplorer()
	{
		this.saves = new SavesManager();
		this.notes = this.saves.loadIndex();
		this.titleBox = new HBox();
		{
			this.titleBox.setPadding(new Insets(10, 0, 0, 0));
			ImageView logoView = new ImageView(new Image("/com/madeorsk/smartnotes/res/Logo.png"));
			this.titleBox.setAlignment(Pos.CENTER);
			this.titleBox.getChildren().add(logoView);
		}
		this.updateList(this.genRoot());
	}

	private void updateList(FolderPath folder)
	{
		this.getChildren().clear();
		this.getChildren().add(this.titleBox);

		this.setSpacing(50);

		this.currentFolder = folder;

		VBox notesList = new VBox();
		notesList.setPadding(new Insets(0, 20, 0, 20));
		notesList.setSpacing(15);
		this.getChildren().add(notesList);

		if (folder.getParent() != null)
			notesList.getChildren().add(new ExplorerItem(true, folder.getParent().setName("Previous folder"), this).setFolderIcon("/com/madeorsk/smartnotes/res/ReturnIcon.png"));

		for (Path p : folder.getContent())
		{
			if (p.isFolder())
				notesList.getChildren().add(new ExplorerItem(true, p, this));
			else
			{
				this.notes.get(((NotePath) p).getNoteId()).load(this.saves, ((NotePath) p).getNoteId());
				notesList.getChildren().add(new ExplorerItem(false, this.notes.get(((NotePath) p).getNoteId()), this));
			}
		}

		final HBox addNoteBox = new HBox();
		{
			addNoteBox.setCursor(Cursor.HAND);
			addNoteBox.setOpacity(0.4);
			addNoteBox.setOnMouseEntered((MouseEvent e) -> {
				FadeTransition transition = new FadeTransition(Duration.millis(200), addNoteBox);
				transition.setFromValue(0.4);
				transition.setToValue(1.0);
				transition.play();
			});
			addNoteBox.setOnMouseExited((MouseEvent e) -> {
				FadeTransition transition = new FadeTransition(Duration.millis(200), addNoteBox);
				transition.setFromValue(1.0);
				transition.setToValue(0.4);
				transition.play();
			});
			addNoteBox.setOnMouseClicked((MouseEvent event) -> {
				TextNote note = new TextNote();
				SmartNotes.instance.setContent(note.getEditBox(NotesExplorer.this));
				int id = NotesExplorer.this.getNextId();
				NotesExplorer.this.notes.put(id, note);

				NotesExplorer.this.saves.saveIndex(NotesExplorer.this.notes);
				note.save(NotesExplorer.this.saves, id);
			});

			addNoteBox.setAlignment(Pos.CENTER_LEFT);
			addNoteBox.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/AddIcon.png")));
			addNoteBox.setSpacing(10);
			Label newNoteLabel = new Label("New note...");
			newNoteLabel.setId("noteItemName");
			addNoteBox.getChildren().add(newNoteLabel);
		}
		notesList.getChildren().add(addNoteBox);
	}

	private FolderPath genRoot()
	{
		FolderPath root = new FolderPath("/", null);
		for (int key : this.notes.keySet())
		{
			Note note = this.notes.get(key);
			if (note.getPaths().isEmpty())
				root.addPath(new NotePath(key));
			else
			{
				for (String path : note.getPaths())
				{
					FolderPath putIn = root;
					String[] foldersString = (path.substring(1).contains("#")) ? path.substring(1).split("#") : Arrays.asList(path.substring(1)).toArray(new String[1]);
					for (String folderString : foldersString)
					{
						if (putIn.containsFolder(folderString))
							putIn = putIn.getFolder(folderString);
						else
						{
							FolderPath newFolder = new FolderPath(folderString, putIn);
							putIn.addPath(newFolder);
							putIn = newFolder;
						}
					}
					putIn.addPath(new NotePath(key));
				}
			}
		}
		return root;
	}

	public void goToFolder(FolderPath path)
	{
		this.updateList(this.getUpdatedFolder(path));
	}

	public void updateCurrentFolder()
	{
		this.updateList(this.getUpdatedFolder(this.currentFolder));
	}

	private FolderPath getUpdatedFolder(FolderPath path)
	{
		if (path.getParent() == null)
			return this.genRoot();
		else
		{
			FolderPath updatedFolder = this.getUpdatedFolder(path.getParent()).getFolder(path.getName());
			if (updatedFolder == null)
				return this.getUpdatedFolder(path.getParent());
			else
				return updatedFolder;
		}
	}

	public void replaceNote(Note oldNote, Note newNote)
	{
		for (int key : this.notes.keySet())
		{
			if (this.notes.get(key).equals(oldNote))
			{
				this.notes.get(key).delete(this.saves, key);
				this.notes.put(key, newNote);
			}
		}
	}

	public void requestSave(final Note note)
	{
		for (int key : NotesExplorer.this.notes.keySet())
			if (NotesExplorer.this.notes.get(key).equals(note))
				note.save(NotesExplorer.this.saves, key);
	}

	public void requestLoad(Note note)
	{
		for (int key : this.notes.keySet())
			if (this.notes.get(key).equals(note))
				note.load(this.saves, key);
	}

	private int getNextId()
	{
		int i = 0;
		for (int key : notes.keySet())
		{
			if (key != i)
				return i;
			i++;
		}
		return notes.keySet().size();
	}

	public void close()
	{
		this.saves.saveIndex(notes);
	}
}
