package hsr.dsa.view;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import hsr.dsa.blockchain.exceptions.BlockChainException;
import hsr.dsa.controller.ChatController;
import hsr.dsa.controller.ControllerManager;
import hsr.dsa.data.DataManagerException;
import hsr.dsa.data.models.Group;
import hsr.dsa.data.models.LocalUser;
import hsr.dsa.data.models.RemoteUser;
import hsr.dsa.data.models.User;
import hsr.dsa.utils.Observable;
import hsr.dsa.utils.Observer;
import hsr.dsa.view.templates.FXTemplate;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;

@SuppressWarnings("restriction")
public class ChatWindowController implements FXController, Observer {
	private static final Logger log = LoggerFactory.getLogger(ChatWindowController.class);
	private FXWindowManager windowManager;
	private LocalUser profile;

	@FXML
	private BorderPane frame;
	@FXML
	private VBox friendList;
	@FXML
	private ScrollPane friendRequestPane;
	@FXML
	private ScrollPane groupList;
	private FXTemplate<User> groupController;
	@FXML
	private ScrollPane activeGroup;

	@Override
	public void setWindowManager(FXWindowManager windowManager) {
		this.windowManager = windowManager;
	}

	@FXML
	@SuppressWarnings("unchecked")
	public void initialize() throws IOException {
		FXMLLoader loader = new FXMLLoader();
		Parent friendRequest = (Parent) loader.load(getClass().getResourceAsStream("/fxml/chatWindow/templates/friendRequest.fxml"));
		FXTemplate<Void> controler = (FXTemplate<Void>) loader.getController();
		controler.setControler(this);
		this.friendRequestPane.setContent(friendRequest);
		
		loader = new FXMLLoader();
		Parent groupCreation = (Parent) loader.load(getClass().getResourceAsStream("/fxml/chatWindow/templates/groupCreation.fxml"));
		this.groupController = loader.getController();
		this.groupController.setControler(this);
		this.groupList.setContent(groupCreation);

		this.setupFriendList();
		
		if (this.profile != null) {
			this.updateFriendList();
		}
	}

	public void logOut() {
		try {
			ControllerManager.getChatController().logout();
			this.windowManager.switchScene("/fxml/start.fxml");
		} catch (BlockChainException | IOException | DataManagerException e) {
			log.error("error while logging out", e);
		}
	}

	@Override
	public void setParamater(Map<String, Object> paramater) {
		this.profile = (LocalUser) paramater.get("User");
		if (this.friendList != null && this.profile != null) {
			try {
				this.updateFriendList();
			} catch (IOException e) {
				log.error("unable to update Friendlist", e);
			}
		}
		if(this.groupController != null) {
			this.groupController.setData(this.profile);
		}
	}

	private void setupFriendList() throws IOException {
		ChatController chatController = ControllerManager.getChatController();
		chatController.getProfile().getFriends().addObserver(this);
	}

	@SuppressWarnings("unchecked")
	private void updateFriendList() throws IOException {
		List<User> friends = this.profile.getFriends();
		
		this.friendList.getChildren().clear();
		
		for (User user : friends) {
			FXMLLoader loader = new FXMLLoader();
			Parent friend = (Parent) loader.load(getClass().getResourceAsStream("/fxml/chatWindow/templates/friend.fxml"));
			FXTemplate<User> templateControler = (FXTemplate<User>) loader.getController();
			templateControler.setData(user);
			templateControler.setControler(this);
			this.friendList.getChildren().add(friend);
		}
	}

	@SuppressWarnings("unchecked")
	public void chat(RemoteUser friend) {
		try {
			FXMLLoader loader = new FXMLLoader();
			Parent chatPane = (Parent) loader.load(getClass().getResourceAsStream("/fxml/chatWindow/templates/chatPane.fxml"));
			FXTemplate<RemoteUser> templateControler = (FXTemplate<RemoteUser>) loader.getController();
			templateControler.setData(friend);
			templateControler.setControler(this);
			this.frame.setCenter(chatPane);
		} catch (IOException e) {
			log.error("unable to load Chat", e);
		}
	}

	@Override
	public void onChange(Observable observable) {
		Platform.runLater(() -> {
			try {
				this.updateFriendList();
			} catch (IOException e) {
				log.error("unable to update Friendlist", e);
			}
		});
	}
	
	@SuppressWarnings("unchecked")
	public void chat(Group group) {
		try {
			FXMLLoader loader = new FXMLLoader();
			Parent chatPane = (Parent) loader.load(getClass().getResourceAsStream("/fxml/chatWindow/templates/groupChatPane.fxml"));
			FXTemplate<Group> templateControler = (FXTemplate<Group>) loader.getController();
			templateControler.setData(group);
			templateControler.setControler(this);
			this.frame.setCenter(chatPane);
			
			loader = new FXMLLoader();
			Parent activeGroup = (Parent) loader.load(getClass().getResourceAsStream("/fxml/chatWindow/templates/groupInvitationRequest.fxml"));
			FXTemplate<Group> controler = (FXTemplate<Group>) loader.getController();
			controler.setControler(this);
			controler.setData(group);
			this.activeGroup.setContent(activeGroup);
		} catch (IOException e) {
			log.error("unable to load Chat", e);
		}
	}
}
