ui.main.MainViewController.java Source code

Java tutorial

Introduction

Here is the source code for ui.main.MainViewController.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ui.main;

import appdata.AppData;
import database.access.DBSingleChat;
import exception.NonAuthorizedException;
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputDialog;
import javafx.scene.control.ToolBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javax.imageio.ImageIO;
import models.callManagement.Call;
import models.chatManagement.ChatsManager;
import models.chatManagement.GroupChatManager;
import models.connectionManagement.ConnectionManager;
import models.contactManagement.ContactsManager;
import models.fileManagement.FileManager;
import org.apache.commons.lang3.RandomStringUtils;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.RosterPacket.ItemType;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferRequest;
import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.JingleSession;
import org.jivesoftware.smackx.jingle.JingleSessionRequest;
import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener;
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
import org.jivesoftware.smackx.jingle.mediaimpl.jmf.JmfMediaManager;
import org.jivesoftware.smackx.jingle.nat.BasicTransportManager;
import org.jivesoftware.smackx.muc.HostedRoom;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.packet.VCard;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import ui.call.CallViewController;
import ui.enhancement.BubbleSpec;
import ui.enhancement.BubbledLabel;
import ui.enhancement.CellRenderer;
import ui.enhancement.GroupCellRenderer;

/**
 * FXML Controller class
 *
 * @author Dulanjaya
 */
public class MainViewController implements Initializable {

    /**
     * Initializes the controller class.
     */
    //Models
    private ConnectionManager connectionManager;
    private ContactsManager contactsManager;
    private ObservableList<RosterEntry> contactList = FXCollections.observableArrayList();
    private ChatsManager chatManager;
    private Chat currentChat;
    private FileManager fileManager;
    private Image defaultAvatar;
    private MultiUserChat currentmuc;

    //common configuration variables
    private boolean isChatUpdated = false;
    private final DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy");
    private final DateTimeFormatter dtfT = DateTimeFormat.forPattern("hh:mm aa");
    private boolean isSingleChat = true;
    private LinkedList<GroupChatManager> loggedMucs = new LinkedList<>();

    //ViewComponents
    @FXML
    private Label presence;

    @FXML
    private Label name;

    @FXML
    private ListView contacts;

    @FXML
    private Label chatterName;

    @FXML
    private Label chatterPresence;

    @FXML
    private TextField message;

    @FXML
    private ImageView myAvatar;

    @FXML
    private ImageView chatterAvatar;

    @FXML
    private VBox chatList;

    @FXML
    private ScrollPane scrollPane;

    @FXML
    private Button friendRequest;

    @FXML
    private CheckMenuItem history;

    @FXML
    private ListView conversations;

    @FXML
    private ToolBar extraComButtons;

    @FXML
    private CheckMenuItem isnotifiable;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        //initialiing the main
        connectionManager = ConnectionManager.getConnectionManager();
        contactsManager = new ContactsManager();
        chatManager = new ChatsManager();
        fileManager = new FileManager();
        //myAccount = new MyAccount();

        //loading the default avatar image
        defaultAvatar = new Image("resources/defaultAvatar.png", 100, 120, true, true);

        showContacts();
        showAccountInfo();
        addContactListener();
        addFileRecieverListener();
        addMessageListener();
        showConversations();
        addRosterListener();
        addConversationListener();
        addCallListener();
        addMessageLimiter();
        setUp();
    }

    //initializing setting
    private void setUp() {
        scrollPane.setFitToWidth(true);
        friendRequest.setVisible(false);
        history.setSelected(true);
        hideExtraComButtons();
        isnotifiable.setSelected(true);
    }

    @FXML
    public void handleExitMenuCall(ActionEvent event) {
        System.exit(0);
    }

    @FXML
    public void handleFileSendButtonAction() {
        sendFile();
    }

    @FXML
    public void handleSendButtonAction(ActionEvent event) {
        if (isSingleChat) {
            sendMessageSC();
        } else {
            sendMessageGC();
        }
    }

    @FXML
    public void handleTemporyButtonAction(ActionEvent event) {
        Task<Void> presenceWatchTask = new Task<Void>() {
            @Override
            public Void call() throws Exception {
                while (true) {
                    updateMessage(connectionManager.getMyPresence());
                    Thread.sleep(1000);
                }
                //return null;
            }
        };

        presenceWatchTask.messageProperty()
                .addListener((obs, oldMessage, newMessage) -> presence.setText(newMessage));
        new Thread(presenceWatchTask).start();
    }

    @FXML
    public void handleLogOutMenuCall(ActionEvent event) {
        connectionManager.logOutServer();
        presence.getScene().getWindow().hide();
    }

    @FXML
    public void handleEditMyAccountMenuCall(ActionEvent event) {
        try {
            //default configuration and initialization of the form
            Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("ui/account/AccountView.fxml"));

            Scene scene = new Scene(root);

            Stage stage = new Stage();

            stage.setScene(scene);
            stage.show();

            stage.setResizable(false);
            stage.setTitle("IMP");
        } catch (IOException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @FXML
    public void handleCallButtonAction(ActionEvent event) {
        takeCall();
    }

    @FXML
    public void handleContactMenuCall(ActionEvent event) {
        //this method displays the contact view
        try {
            //default configuration and initialization of the form
            Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("ui/contacts/ContactsView.fxml"));

            Scene scene = new Scene(root);

            Stage stage = new Stage();

            stage.setScene(scene);
            stage.show();

            stage.setResizable(false);
            stage.setTitle("IMP : Contacts");
        } catch (IOException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @FXML
    public void handleClearHistoryButtonCall(ActionEvent event) {
        clearHistory();
    }

    @FXML
    public void handleNewConvesationMenuCall(ActionEvent event) {
        createNewConversation();
    }

    @FXML
    public void handleSendImageButtonAction(ActionEvent event) {
        sendImage();
    }

    @FXML
    public void handleFriendRequestButtonAction(ActionEvent event) {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("Confirmation");
        alert.setHeaderText("Accept Friend Request!");
        alert.setContentText("Are you sure to add the this user as a friend?");

        ButtonType buttonTpeYes = new ButtonType("Yes");
        ButtonType buttonTypeNo = new ButtonType("Not Now");
        ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);

        alert.getButtonTypes().setAll(buttonTpeYes, buttonTypeNo, buttonTypeCancel);

        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == buttonTpeYes) {
            contactsManager.acceptFriend(currentChat.getParticipant());
            friendRequest.setVisible(false);
        } else if (result.get() == buttonTypeNo) {
            // ... no thing to do
        } else {
            // ... user chose CANCEL or closed the dialog
        }

    }

    @FXML
    public void handleAboutMenuCall(ActionEvent event) {
        //this method displays the about
        try {
            //default configuration and initialization of the form
            Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("ui/about/AboutView.fxml"));

            Scene scene = new Scene(root);

            Stage stage = new Stage();

            stage.setScene(scene);
            stage.show();

            stage.setResizable(false);
            stage.setTitle("About");
        } catch (IOException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //Controller Logic
    private void showAccountInfo() {
        //this method shows the account name and presence
        //create a thread to check the user connected online or not
        Task<Void> presenceWatchTask = new Task<Void>() {
            @Override
            public Void call() throws Exception {
                while (true) {
                    updateMessage(connectionManager.getMyPresence());
                    Thread.sleep(1000);
                }
                //return null;
            }
        };

        presenceWatchTask.messageProperty()
                .addListener((obs, oldMessage, newMessage) -> presence.setText(newMessage));
        new Thread(presenceWatchTask).start();
        name.setText(connectionManager.getMyUsername());
        try {
            if (connectionManager.getMyProfileAvatar() != null) {
                myAvatar.setImage(connectionManager.getMyProfileAvatar());

            } else {
                myAvatar.setImage(defaultAvatar);
            }
        } catch (IOException e) {
            myAvatar.setImage(defaultAvatar);
        } catch (XMPPException e) {
            myAvatar.setImage(defaultAvatar);
        } catch (NullPointerException e) {
            myAvatar.setImage(defaultAvatar);
        } finally {
            myAvatar.setFitHeight(120);
            myAvatar.setFitWidth(100);
        }
    }

    private void sendMessageSC() {
        if (currentChat == null) {
            return;
        }
        try {
            ItemType type = contactsManager.getUserType(currentChat.getParticipant());
            if (type.equals(ItemType.none)) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("Attention!");
                alert.setHeaderText("The user is not available for you!");
                alert.setContentText(
                        "The user has not accepted the Friend Request." + " The user is not available for you.");
                alert.showAndWait();
                return;
            } else if (type.equals(ItemType.from)) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("Attention!");
                alert.setHeaderText("An unaccepted user!");
                alert.setContentText("You have not accepted the Friend Request."
                        + " You can not send any messages until you accept the friend request.");
                alert.showAndWait();
                return;
            } else if (type.equals(ItemType.to)) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("Attention!");
                alert.setHeaderText("The user has not accepted!");
                alert.setContentText("The user has not accepted the Friend Request."
                        + " You can not send any messages until the user accepts the friend request.");
                alert.showAndWait();
                return;
            }
            if (message.getText().isEmpty()) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("IMP");
                alert.setHeaderText("Message is empty!");
                alert.setContentText("You can not send empty messages.");
                alert.showAndWait();
                return;
            }
            try {
                currentChat.sendMessage(message.getText()); //sends message
                if (history.isSelected()) {
                    DBSingleChat.saveTextMessage(currentChat.getParticipant(), false, message.getText(),
                            new Timestamp(System.currentTimeMillis()));
                }

                paintSendMessage(message.getText().trim(), dtfT.print(DateTime.now())); //paints the sent item
                message.setText(""); //clears the sent text
                Task tt = new Task() {
                    @Override
                    protected Object call() throws Exception {
                        Thread.sleep(500);
                        return new Object();
                    }
                };

                tt.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

                Thread thread1 = new Thread(tt);
                thread1.start();
            } catch (XMPPException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (NullPointerException e) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("IMP");
            alert.setHeaderText("User is unavailable!");
            alert.setContentText("The user is unavailable for you!.");
            alert.showAndWait();
            return;
        }

    }

    private void sendFile() {
        if (!contactsManager.getAvailabilityforSharing(currentChat.getParticipant())) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("The user is not available!");
            alert.setContentText("The file receiving user should be available online to receive the file.");
            alert.showAndWait();
            return;
        }
        ItemType type = contactsManager.getUserType(currentChat.getParticipant());

        if (type.equals(ItemType.none)) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("This user is not available for you!");
            alert.setContentText(
                    "The user has not accepted the Friend Request." + " The user is not available for you.");
            alert.showAndWait();
            return;
        } else if (type.equals(ItemType.from)) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("An unaccepted user!");
            alert.setContentText("You have not accepted the Friend Request."
                    + " You can not send any messages until you accept the friend request.");
            alert.showAndWait();
            return;
        } else if (type.equals(ItemType.to)) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("The user has not accepted!");
            alert.setContentText("The user has not accepted the Friend Request."
                    + " You can not send any messages until the user accepts the friend request.");
            alert.showAndWait();
            return;
        }
        if (!contactsManager.getAvailabilityforSharing(currentChat.getParticipant())) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("The user is not available!");
            alert.setContentText("The file receiving user should be available online to receive the file.");
            alert.showAndWait();
            return;
        }
        FileChooser fc = new FileChooser();
        File file = fc.showOpenDialog(presence.getScene().getWindow());
        if (file == null) {
            return;
        }
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    fileManager.sendFile(file, currentChat.getParticipant());
                    if (history.isSelected()) {
                        Timestamp time = new Timestamp(System.currentTimeMillis());
                        DBSingleChat.saveFileMessage(currentChat.getParticipant(), false, file.getPath(), time);
                    }

                    paintSentFile(currentChat, file.getAbsolutePath(), dtfT.print(DateTime.now()));
                    Task tt = new Task() {
                        @Override
                        protected Object call() throws Exception {
                            Thread.sleep(500);
                            return new Object();
                        }
                    };

                    tt.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

                    Thread thread1 = new Thread(tt);
                    thread1.start();
                } catch (FileNotFoundException ex) {
                    Alert alert = new Alert(Alert.AlertType.ERROR);
                    alert.setTitle("IMP");
                    alert.setHeaderText("File is not Found!");
                    alert.setContentText("File you selected does not exist.");
                    alert.showAndWait();
                    return;
                }
            }
        });
        t.start();
    }

    private void sendImage() {
        if (!contactsManager.getAvailabilityforSharing(currentChat.getParticipant())) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("The user is not available!");
            alert.setContentText("The file receiving user should be available online to receive the file.");
            alert.showAndWait();
            return;
        }
        ItemType type = contactsManager.getUserType(currentChat.getParticipant());
        if (type.equals(ItemType.none)) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("The is not available for you!");
            alert.setContentText(
                    "The user has not accepted the Friend Request." + " The user is not available for you.");
            alert.showAndWait();
            return;
        } else if (type.equals(ItemType.from)) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("The user has not accepted!");
            alert.setContentText("The user has not accepted the Friend Request."
                    + " You can not send any messages until the user accepts the friend request.");
            alert.showAndWait();
            return;
        } else if (type.equals(ItemType.to)) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Attention!");
            alert.setHeaderText("The user has not accepted!");
            alert.setContentText("The user has not accepted the Friend Request."
                    + " You can not send any messages until the user accepts the friend request.");
            alert.showAndWait();
            return;
        }
        try {
            FileChooser fc = new FileChooser();
            fc.setTitle("Choose an image to send");
            fc.getExtensionFilters().addAll(
                    new FileChooser.ExtensionFilter("All Images", "*.jpg*", "*.png", "*.bmp"),
                    new FileChooser.ExtensionFilter("JPG", "*.jpg"),
                    new FileChooser.ExtensionFilter("PNG", "*.png"),
                    new FileChooser.ExtensionFilter("BMP", "*.bmp"));

            File file = fc.showOpenDialog(presence.getScene().getWindow());
            if (file == null) {
                return;
            }
            BufferedImage image = ImageIO.read(file);
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        fileManager.sendFile(file, currentChat.getParticipant());
                        if (history.isSelected()) {
                            Timestamp time = new Timestamp(System.currentTimeMillis());
                            DBSingleChat.savePictureMessage(currentChat.getParticipant(), false, file.getPath(),
                                    time);
                        }

                        paintSentPhoto(currentChat, file, dtfT.print(DateTime.now()));

                        Task tt = new Task() {
                            @Override
                            protected Object call() throws Exception {
                                Thread.sleep(500);
                                return new Object();
                            }
                        };

                        tt.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

                        Thread thread1 = new Thread(tt);
                        thread1.start();
                    } catch (FileNotFoundException ex) {
                        Alert alert = new Alert(Alert.AlertType.ERROR);
                        alert.setTitle("IMP");
                        alert.setHeaderText("File is not Found!");
                        alert.setContentText("File you selected does not exist.");
                        alert.showAndWait();
                        return;
                    }
                }
            });
            t.start();
        } catch (IOException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void takeCall() {
        if (contactsManager.getAvailabilityforCalling(currentChat.getParticipant())) {
            try {
                //default configuration and initialization of the form
                Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("ui/call/CallView.fxml"));

                Scene scene = new Scene(root);

                Stage stage = new Stage();

                stage.setScene(scene);
                stage.show();

                stage.setResizable(false);
                stage.setTitle("IMP : Voice");
            } catch (IOException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("IMP");
            alert.setHeaderText("Username is unavailable for calling!");
            alert.setContentText("The user is not available for calling. "
                    + "Please contact the user or the server administrator");
            alert.showAndWait();
        }
    }

    private void showContacts() {
        //display contacts in the contact list view
        List<RosterEntry> col = new ArrayList<RosterEntry>(contactsManager.getContacts());
        Collections.sort(col, (left, right) -> left.getUser().compareTo(right.getUser()));
        contactList = FXCollections.observableArrayList(col);
        contacts.setItems(contactList);
        contacts.setCellFactory(new CellRenderer());
    }

    private void addContactListener() {
        //this method adds a contacts list listener
        System.gc();
        contacts.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                if (newValue == null) {
                    return;
                }
                conversations.getSelectionModel().clearSelection();
                chatList.getChildren().clear();
                isSingleChat = true;
                if (((RosterEntry) newValue).getType().equals(ItemType.from)) {
                    friendRequest.setVisible(true);
                } else {
                    friendRequest.setVisible(false);
                }
                Call.dialUser = ((RosterEntry) newValue).getUser();
                String chatterNameTem = ((RosterEntry) newValue).getUser(); //get reciever
                String chatterNameTem2 = chatterNameTem;

                ResultSet rs = DBSingleChat.readMessages(chatterNameTem); //load old messages

                chatterNameTem = chatterNameTem.substring(0, chatterNameTem.indexOf("@"));
                chatterNameTem = Character.toUpperCase(chatterNameTem.charAt(0)) + chatterNameTem.substring(1);

                chatterName.setText(chatterNameTem); //set chat box to recievers contacts
                currentChat = chatManager.createChat(((RosterEntry) newValue).getUser()); //set the current chat
                chatterPresence.setText(contactsManager.getPresence(((RosterEntry) newValue).getUser()));

                VCard vcard = new VCard(); //vcard to load presence
                try {
                    vcard.load(connectionManager.getXMPPConnection(), currentChat.getParticipant());
                    if (vcard.getAvatar() != null) {
                        BufferedImage img = ImageIO.read(new ByteArrayInputStream(vcard.getAvatar()));
                        Image image = SwingFXUtils.toFXImage(img, null);
                        chatterAvatar.setImage(image);
                    } else {
                        chatterAvatar.setImage(defaultAvatar);
                    }
                } catch (XMPPException ex) {
                    chatterAvatar.setImage(defaultAvatar);
                } catch (IOException ex) {
                    Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
                } catch (NullPointerException ex) {
                    chatterAvatar.setImage(defaultAvatar);
                } finally {
                    chatterAvatar.setFitHeight(120);
                    chatterAvatar.setFitWidth(100);
                }

                //display old messages -> current chat is required to be set as a prerequisit
                loadChat(chatterNameTem2);
                Task t = new Task() {
                    @Override
                    protected Object call() throws Exception {
                        Thread.sleep(500);
                        return new Object();
                    }
                };

                t.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

                Thread thread1 = new Thread(t);
                thread1.start();

                //show extra options
                showExtraComButtons();
            }
        });

    }

    private void addFileRecieverListener() {
        //adds a file recieve listener to the application
        FileTransferManager ftm = fileManager.getFTM();
        ftm.addFileTransferListener((FileTransferRequest ftr) -> {
            IncomingFileTransfer transfer = ftr.accept(); //accepts the request

            try {
                //creates file recievedFile with a particular file name
                //stores on the predefined location
                File recivedFile = new File(appdata.AppData.downloadPath
                        + RandomStringUtils.randomAlphanumeric(10).toUpperCase() + ftr.getFileName());
                if (!recivedFile.exists()) {
                    File newFile = new File(appdata.AppData.downloadPath);
                    if (!newFile.exists()) {
                        newFile.mkdir();
                    }
                }

                transfer.recieveFile(recivedFile); //get the data stream of the message to file

                //shows the file received notification
                showNotifications(ftr.getRequestor(), "You have received a new File");

                if (ftr.getMimeType() == null) {
                    //if the recieved file is not an image then triggers here
                    //file path will be saved in the database by this
                    String participant = ftr.getRequestor();
                    if (participant.contains("/")) {
                        participant = participant.substring(0, participant.indexOf("/")); //removing the requester's service
                    }
                    Timestamp time = new Timestamp(System.currentTimeMillis()); //time of the recieve is added
                    if (history.isSelected()) {
                        DBSingleChat.saveFileMessage(participant, true, recivedFile.getPath(), time);
                    }
                    DateTime _time = new DateTime(time.getTime());
                    paintReceivedFile(currentChat, recivedFile.getPath(), dtfT.print(_time));
                }
                if (ftr.getMimeType().contains("image")) {
                    //saves the picture as a path in the database
                    String participant = ftr.getRequestor();
                    if (participant.contains("/")) {
                        participant = participant.substring(0, participant.indexOf("/")); //removing the requester's service
                    }
                    Timestamp time = new Timestamp(System.currentTimeMillis()); //time of the recieve is added
                    if (history.isSelected()) {
                        DBSingleChat.savePictureMessage(participant, true, recivedFile.getPath(), time); //ask to save
                    }

                    // if the file is an image, displays the image in the chat view
                    if (ftr.getRequestor().contains(currentChat.getParticipant())) {
                        paintReceivedPhotoOnTransmit(currentChat, recivedFile, dtfT.print(DateTime.now()));

                    }

                } else {
                    //if the recieved file is not an image then triggers here
                    //file path will be saved in the database by this
                    String participant = ftr.getRequestor();
                    if (participant.contains("/")) {
                        participant = participant.substring(0, participant.indexOf("/")); //removing the requester's service
                    }
                    Timestamp time = new Timestamp(System.currentTimeMillis()); //time of the recieve is added
                    if (history.isSelected()) {
                        DBSingleChat.saveFileMessage(participant, true, recivedFile.getPath(), time);
                    }

                    DateTime _time = new DateTime(time.getTime());
                    paintReceivedFile(currentChat, recivedFile.getPath(), dtfT.print(_time));
                }

            } catch (XMPPException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
    }

    private void addMessageListener() {
        //adds a message listener for the chat application

        //remove the offlinemessagelistener to avoid dual listening
        connectionManager.removeOfflinePacketListener();

        //adds the listener
        chatManager.getChatManager().addChatListener(new ChatManagerListener() {
            @Override
            public void chatCreated(Chat chat, boolean bln) {
                chat.addMessageListener(new MessageListener() {
                    @Override
                    public void processMessage(Chat chat, Message msg) {
                        if (!msg.getBody().equals("")) {
                            Timestamp time = new Timestamp(System.currentTimeMillis());
                            String participant;
                            if (chat.getParticipant().contains("/")) {
                                participant = chat.getParticipant().substring(0,
                                        chat.getParticipant().indexOf("/"));
                            } else {
                                participant = chat.getParticipant();
                            }
                            if (history.isSelected()) {
                                DBSingleChat.saveTextMessage(participant, true, msg.getBody(), time);
                            }
                        }
                        if (currentChat != null) {
                            if (chat.getParticipant().contains(currentChat.getParticipant())) {
                                if (!msg.getBody().equals("")) {
                                    DateTime time = DateTime.now();
                                    paintReceivedMessage(chat, msg.getBody(), dtfT.print(time));
                                    Task t = new Task() {
                                        @Override
                                        protected Object call() throws Exception {
                                            Thread.sleep(500);
                                            return new Object();
                                        }
                                    };

                                    t.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

                                    Thread thread1 = new Thread(t);
                                    thread1.start();
                                }
                            } else {
                                //shows the file received notification
                                showNotifications(msg.getFrom(), msg.getBody());

                            }
                        } else {
                            //if the current chat is not selected
                            showNotifications(msg.getFrom(), msg.getBody());
                        }
                    }
                });

            }
        });
    }

    private void addConversationListener() {
        conversations.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                if (newValue == null) {
                    chatterName.setText("");
                    return;
                }
                contacts.getSelectionModel().clearSelection();
                chatList.getChildren().clear();
                chatterName.setText(((HostedRoom) newValue).getName());
                chatterPresence.setText("Group Chat");
                chatterAvatar.setImage(new Image("resources/guest.png", 100, 100, true, true));

                Iterator<GroupChatManager> i = loggedMucs.iterator();
                while (i.hasNext()) {
                    GroupChatManager gcm = i.next();
                    if (gcm.getRoom().equals(((HostedRoom) newValue).getJid())) {
                        currentmuc = gcm.getMuc();
                        //getConversationHistory();
                        reloadConversationMessages(gcm.getMsgList());
                        return;
                    }
                }

                try {
                    currentmuc = chatManager.joinRoom(((HostedRoom) newValue).getJid());
                    loggedMucs.add(new GroupChatManager(currentmuc, getConversationHistory()));
                } catch (NonAuthorizedException e) {

                    TextInputDialog dialog = new TextInputDialog();
                    dialog.setTitle("Closed Conference Login");
                    dialog.setHeaderText("Password Required!");
                    dialog.setContentText("Password :");

                    Optional<String> result = dialog.showAndWait();
                    if (result.isPresent()) {
                        try {
                            currentmuc = chatManager.joinPrivateRoom(((HostedRoom) newValue).getJid(),
                                    result.get());
                            loggedMucs.add(new GroupChatManager(currentmuc, getConversationHistory()));
                        } catch (NonAuthorizedException ex) {
                            Alert alert = new Alert(Alert.AlertType.INFORMATION);
                            alert.setTitle("Invalid Password!");
                            alert.setHeaderText("Conversation cannot be displayed!");
                            alert.setContentText(
                                    "The password for the conversation is incorrect. Please try again!");
                            alert.showAndWait();
                            return;
                        }
                    }
                }

                ChatsManager.setSelectedConversation(newValue.toString());
                isSingleChat = false;

                hideExtraComButtons();
                addConversationMessageListener();

            }
        });
    }

    private synchronized void paintDate(Chat chat, String day) {
        //this method draws the recievied text message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {

                VBox vbox = new VBox(); //to add text

                //chat message
                Label l = new Label(day);
                l.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, null, null)));

                HBox hbox = new HBox();
                hbox.setAlignment(Pos.CENTER);
                hbox.getChildren().addAll(l);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());

        });

        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            try {
                t.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
            //t.setDaemon(true);
            t.start();
            scrollPane.setVvalue(scrollPane.getHmax());
        }
    }

    private synchronized void paintReceivedMessage(Chat chat, String msg, String time) {
        //this method draws the recievied text message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {

                VBox vbox = new VBox(); //to add text

                ImageView imageRec = new ImageView(chatterAvatar.getImage()); //image
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                String strChatterName = chat.getParticipant(); //add name of the chatter with light color
                strChatterName = Character.toUpperCase(strChatterName.charAt(0))
                        + strChatterName.substring(1, strChatterName.indexOf("@"));
                Label chatterName = new Label(strChatterName);
                chatterName.setDisable(true);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                //chat message
                BubbledLabel bbl = new BubbledLabel();
                bbl.setText(msg);
                bbl.setBackground(new Background(new BackgroundFill(Color.GAINSBORO, null, null)));

                vbox.getChildren().addAll(chatterName, bbl, timeL);
                vbox.setAlignment(Pos.CENTER_RIGHT);
                HBox hbox = new HBox();
                bbl.setBubbleSpec(BubbleSpec.FACE_LEFT_CENTER);
                hbox.getChildren().addAll(imageRec, vbox);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());

        });

        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            //t.setDaemon(true);
            t.start();
            try {
                t.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
            scrollPane.setVvalue(scrollPane.getHmax());
        }
    }

    private synchronized void paintWarningInRecieve(Chat chat, String Warning, String time) {
        //this method draws the recievied text message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {

                VBox vbox = new VBox(); //to add text

                ImageView imageRec = new ImageView(chatterAvatar.getImage()); //image
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                String strChatterName = chat.getParticipant(); //add name of the chatter with light color
                strChatterName = Character.toUpperCase(strChatterName.charAt(0))
                        + strChatterName.substring(1, strChatterName.indexOf("@"));
                Label chatterName = new Label(strChatterName);
                chatterName.setDisable(true);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                //chat message
                BubbledLabel bbl = new BubbledLabel();
                bbl.setText(Warning);
                bbl.setBackground(new Background(new BackgroundFill(Color.RED, null, null)));

                vbox.getChildren().addAll(chatterName, bbl, timeL);
                vbox.setAlignment(Pos.CENTER_RIGHT);
                HBox hbox = new HBox();
                bbl.setBubbleSpec(BubbleSpec.FACE_LEFT_CENTER);
                hbox.getChildren().addAll(imageRec, vbox);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());
            scrollPane.setVvalue(scrollPane.getHmax());
            scrollPane.setVvalue(scrollPane.getHmax());
        });

        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            t.start();
            try {
                t.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
            //t.setDaemon(true);

        }
    }

    private synchronized void paintReceivedPhotoLoad(Chat chat, File recievedFile, String time) {
        //this method paints the recieved picture message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {
                Thread.sleep(100);
                VBox vbox = new VBox(); //to add text

                ImageView imageRec = new ImageView(chatterAvatar.getImage()); //image
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                String strChatterName = chat.getParticipant(); //add name of the chatter with light color
                strChatterName = Character.toUpperCase(strChatterName.charAt(0))
                        + strChatterName.substring(1, strChatterName.indexOf("@"));
                Label chatterName = new Label(strChatterName);
                chatterName.setDisable(true);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                try {
                    Image recievedImage = SwingFXUtils.toFXImage(ImageIO.read(recievedFile), null);
                    ImageView receivedImageView = new ImageView(recievedImage);
                    receivedImageView.setFitHeight(300);
                    receivedImageView.setFitWidth(300);
                    receivedImageView.setPreserveRatio(true);

                    receivedImageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            if (event.getButton() == MouseButton.PRIMARY) {
                                Desktop dt = Desktop.getDesktop();
                                try {
                                    dt.open(recievedFile);
                                } catch (IOException ex) {
                                    Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null,
                                            ex);
                                }
                            }
                        }
                    });

                    receivedImageView.setOnMouseEntered(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            chatList.getScene().setCursor(Cursor.HAND);
                        }
                    });

                    receivedImageView.setOnMouseExited(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            chatList.getScene().setCursor(Cursor.DEFAULT);
                        }
                    });

                    vbox.getChildren().addAll(chatterName, receivedImageView, timeL);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                vbox.setAlignment(Pos.CENTER_RIGHT);
                HBox hbox = new HBox();
                //bbl.setBubbleSpec(BubbleSpec.FACE_LEFT_CENTER);
                hbox.getChildren().addAll(imageRec, vbox);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());
        });

        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            t.start();
            try {
                t.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

    private synchronized void paintReceivedPhotoOnTransmit(Chat chat, File recievedFile, String time) {
        //this method paints the recieved picture message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {
                VBox vbox = new VBox(); //to add text
                Thread.sleep(2000);
                ImageView imageRec = new ImageView(chatterAvatar.getImage()); //image
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                String strChatterName = chat.getParticipant(); //add name of the chatter with light color
                strChatterName = Character.toUpperCase(strChatterName.charAt(0))
                        + strChatterName.substring(1, strChatterName.indexOf("@"));
                Label chatterName = new Label(strChatterName);
                chatterName.setDisable(true);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                try {
                    Image recievedImage = SwingFXUtils.toFXImage(ImageIO.read(recievedFile), null);
                    ImageView receivedImageView = new ImageView(recievedImage);
                    receivedImageView.setFitHeight(300);
                    receivedImageView.setFitWidth(300);
                    receivedImageView.setPreserveRatio(true);

                    receivedImageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            if (event.getButton() == MouseButton.PRIMARY) {
                                Desktop dt = Desktop.getDesktop();
                                try {
                                    dt.open(recievedFile);
                                } catch (IOException ex) {
                                    Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null,
                                            ex);
                                }
                            }
                        }
                    });

                    receivedImageView.setOnMouseEntered(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            chatList.getScene().setCursor(Cursor.HAND);
                        }
                    });

                    receivedImageView.setOnMouseExited(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            chatList.getScene().setCursor(Cursor.DEFAULT);
                        }
                    });

                    vbox.getChildren().addAll(chatterName, receivedImageView, timeL);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                vbox.setAlignment(Pos.CENTER_RIGHT);
                HBox hbox = new HBox();
                hbox.getChildren().addAll(imageRec, vbox);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());
        });
        //set the received chat message appear on the screen
        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            t.start();
        }
        Task t = new Task() {
            @Override
            protected Object call() throws Exception {
                Thread.sleep(2500);
                return new Object();
            }
        };

        t.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

        Thread thread1 = new Thread(t);
        thread1.start();
    }

    private synchronized void paintReceivedFile(Chat chat, String path, String time) {
        //this method paints the recieved picture message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {
                Thread.sleep(100);
                VBox vbox = new VBox(); //to add text

                ImageView imageRec = new ImageView(chatterAvatar.getImage()); //image
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                String strChatterName = chat.getParticipant(); //add name of the chatter with light color
                strChatterName = Character.toUpperCase(strChatterName.charAt(0))
                        + strChatterName.substring(1, strChatterName.indexOf("@"));
                Label chatterName = new Label(strChatterName);
                chatterName.setDisable(true);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                Hyperlink link = new Hyperlink("File Recieved: " + path);
                link.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<javafx.scene.input.MouseEvent>() {
                    @Override
                    public void handle(javafx.scene.input.MouseEvent event) {
                        try {
                            if (event.getButton() == MouseButton.PRIMARY) {
                                Runtime.getRuntime().exec("explorer.exe /select," + path);
                            }
                        } catch (IOException ex) {
                            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                });
                vbox.getChildren().addAll(chatterName, link, timeL);
                vbox.setAlignment(Pos.CENTER_RIGHT);
                HBox hbox = new HBox();
                //bbl.setBubbleSpec(BubbleSpec.FACE_LEFT_CENTER);
                hbox.getChildren().addAll(imageRec, vbox);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());
        });

        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            //t.setDaemon(true);
            t.start();
            try {
                t.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        //set the received chat message appear on the screen
        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            t.start();
        }
        Task t = new Task() {
            @Override
            protected Object call() throws Exception {
                Thread.sleep(2500);
                return new Object();
            }
        };

        t.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

        Thread thread1 = new Thread(t);
        thread1.start();

    }

    private synchronized void paintSentPhoto(Chat chat, File file, String time) {
        //this method paints the recieved picture message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {
                //                Thread.sleep(100);
                VBox vbox = new VBox(); //to add text

                ImageView imageRec = new ImageView(myAvatar.getImage()); //image
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                Label chatterName = new Label(name.getText());
                chatterName.setDisable(true);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                try {
                    Image recievedImage = SwingFXUtils.toFXImage(ImageIO.read(file), null);
                    ImageView receivedImageView = new ImageView(recievedImage);
                    receivedImageView.setFitHeight(300);
                    receivedImageView.setFitWidth(300);
                    receivedImageView.setPreserveRatio(true);

                    receivedImageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            if (event.getButton() == MouseButton.PRIMARY) {
                                Desktop dt = Desktop.getDesktop();
                                try {
                                    dt.open(file);
                                } catch (IOException ex) {
                                    Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null,
                                            ex);
                                }
                            }
                        }
                    });

                    receivedImageView.setOnMouseEntered(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            chatList.getScene().setCursor(Cursor.HAND);
                        }
                    });

                    receivedImageView.setOnMouseExited(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            chatList.getScene().setCursor(Cursor.DEFAULT);
                        }
                    });

                    vbox.getChildren().addAll(chatterName, receivedImageView, timeL);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                vbox.setAlignment(Pos.CENTER_LEFT);
                HBox hbox = new HBox();
                hbox.setAlignment(Pos.CENTER_RIGHT);
                //bbl.setBubbleSpec(BubbleSpec.FACE_LEFT_CENTER);
                hbox.getChildren().addAll(vbox, imageRec);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());
        });

        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            t.start();
            try {
                t.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private synchronized void paintSendMessage(String msg, String time) {
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {
                VBox vbox = new VBox(); //to add text

                ImageView imageRec = new ImageView(myAvatar.getImage());
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                Label myName = new Label(name.getText());
                myName.setDisable(true);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                BubbledLabel bbl = new BubbledLabel();
                bbl.setText(msg);
                bbl.setBackground(new Background(new BackgroundFill(Color.LIGHTBLUE, null, null)));
                HBox hbox = new HBox();
                hbox.setAlignment(Pos.TOP_RIGHT);
                bbl.setBubbleSpec(BubbleSpec.FACE_RIGHT_CENTER);

                vbox.getChildren().addAll(myName, bbl, timeL);

                hbox.getChildren().addAll(vbox, imageRec);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());
        });
        Thread t = new Thread(recievedMessages);
        t.setDaemon(true);
        t.start();
        try {
            t.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private synchronized void paintSentFile(Chat chat, String path, String time) {
        //this method paints the recieved picture message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {
                Thread.sleep(100);
                VBox vbox = new VBox(); //to add text

                ImageView imageRec = new ImageView(myAvatar.getImage()); //image
                imageRec.setFitHeight(60);
                imageRec.setFitWidth(50);

                Label timeL = new Label(time);
                timeL.setDisable(true);
                timeL.setFont(new Font("Arial", 10));

                Label chatterName = new Label(name.getText());
                chatterName.setDisable(true);

                Hyperlink link = new Hyperlink("File Sent: " + path);
                link.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<javafx.scene.input.MouseEvent>() {
                    @Override
                    public void handle(javafx.scene.input.MouseEvent event) {
                        try {
                            if (event.getButton() == MouseButton.PRIMARY) {
                                Runtime.getRuntime().exec("explorer.exe /select," + path);
                            }
                        } catch (IOException ex) {
                            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                });
                vbox.getChildren().addAll(chatterName, link, timeL);
                vbox.setAlignment(Pos.CENTER_LEFT);
                HBox hbox = new HBox();
                hbox.setAlignment(Pos.CENTER_RIGHT);
                //bbl.setBubbleSpec(BubbleSpec.FACE_LEFT_CENTER);
                hbox.getChildren().addAll(vbox, imageRec);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());
        });

        if (chat.getParticipant().contains(currentChat.getParticipant())) {
            Thread t = new Thread(recievedMessages);
            t.start();
            try {
                t.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }

    private void showConversations() {
        //show conversations in the conversaation list view
        try {
            ObservableList<HostedRoom> convs = FXCollections.observableArrayList();
            Collection<HostedRoom> c = MultiUserChat.getHostedRooms(connectionManager.getXMPPConnection(),
                    "conference.".concat(connectionManager.getXMPPConnection().getServiceName()));
            if (c == null) {

            } else if (c.isEmpty()) {

            } else {
                Iterator<HostedRoom> i = c.iterator();
                while (i.hasNext()) {
                    convs.add(i.next());
                }
                conversations.setItems(convs);
                conversations.setCellFactory(new GroupCellRenderer());
            }
        } catch (XMPPException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void clearHistory() {
        //clears the chat history
        if (currentChat == null) {
            return;
        } else {
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.setTitle("Confirmation");
            alert.setHeaderText("Confirm to Clear History");
            alert.setContentText("Are you sure to clear the current history?");

            ButtonType buttonTpeYes = new ButtonType("Yes");
            ButtonType buttonTypeNo = new ButtonType("No");
            ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);

            alert.getButtonTypes().setAll(buttonTpeYes, buttonTypeNo, buttonTypeCancel);

            Optional<ButtonType> result = alert.showAndWait();
            if (result.get() == buttonTpeYes) {
                DBSingleChat.clearHistory(currentChat.getParticipant());
                chatList.getChildren().clear();
            } else if (result.get() == buttonTypeNo) {
                // ... no thing to do
            } else {
                // ... user chose CANCEL or closed the dialog
            }
        }
    }

    private void loadChat(String chatterName) {
        if (chatterName.contains("/")) {
            chatterName = chatterName.substring(0, chatterName.indexOf("/")); //removing the requester's service
        }
        ResultSet rs = DBSingleChat.readMessages(chatterName); //load old messages
        //display old messages -> current chat is required to be set as a prerequisit
        String messageContent;
        boolean isRecieved;
        String type;
        Timestamp time;
        DateTime pre = null;
        DateTime cur;
        try {
            if (rs == null) {
                return;
            }
            while (rs.next()) {
                messageContent = rs.getString("messagecontent");
                isRecieved = rs.getBoolean("sent");
                type = rs.getString("type");

                //time of each message
                time = rs.getTimestamp("time_");

                cur = new DateTime(time.getTime());
                if (null == pre) {

                    pre = cur;
                    paintDate(currentChat, dtf.print(cur));
                } else if (pre.toLocalDate().compareTo(cur.toLocalDate()) != 0) {
                    //creates a new date to print
                    pre = cur;
                    paintDate(currentChat, dtf.print(cur));

                }
                if (type.equals("T")) {
                    if (isRecieved) {
                        paintReceivedMessage(currentChat, messageContent, dtfT.print(cur));
                    } else {
                        paintSendMessage(messageContent, dtfT.print(cur));
                    }
                } else if (type.equals("P")) {
                    if (isRecieved) {
                        File file = new File(messageContent);
                        if (!file.exists()) {
                            paintWarningInRecieve(currentChat, "Photo Cannot be Loaded!", dtfT.print(cur));
                        } else {
                            paintReceivedPhotoLoad(currentChat, file, dtfT.print(cur));
                        }
                    } else {
                        File file = new File(messageContent);
                        if (!file.exists()) {
                            paintWarningInRecieve(currentChat, "Photo Cannot be Loaded!", dtfT.print(cur));
                        } else {
                            paintSentPhoto(currentChat, file, dtfT.print(cur));
                        }
                    }
                } else if (type.equals("F")) {
                    if (isRecieved) {
                        File file = new File(messageContent);
                        if (!file.exists()) {
                            paintWarningInRecieve(currentChat, "File (" + messageContent + ") does not exist!",
                                    dtfT.print(cur));
                        } else {
                            paintReceivedFile(currentChat, messageContent, dtfT.print(cur));
                        }
                    } else {
                        File file = new File(messageContent);
                        if (!file.exists()) {
                            paintWarningInRecieve(currentChat, "File (" + messageContent + ") does not exist!",
                                    dtfT.print(cur));
                        } else {
                            paintReceivedFile(currentChat, messageContent, dtfT.print(cur));
                        }
                        paintSentFile(currentChat, file.getPath(), dtfT.print(cur));
                    }
                }
            }
            if (null == pre) {
                pre = new DateTime(System.currentTimeMillis());
                paintDate(currentChat, dtf.print(pre));
            } else if (pre.toLocalDate().compareTo((new DateTime(System.currentTimeMillis())).toLocalDate()) != 0) {
                pre = new DateTime(System.currentTimeMillis());
                paintDate(currentChat, dtf.print(pre));
            }
        } catch (SQLException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void createNewConversation() {
        //this method displays the new convesation create view
        try {
            //default configuration and initialization of the form
            Parent root = FXMLLoader
                    .load(getClass().getClassLoader().getResource("ui/conversation/ConversationView.fxml"));

            Scene scene = new Scene(root);

            Stage stage = new Stage();

            stage.setScene(scene);
            stage.show();

            stage.setResizable(false);
            stage.setTitle("IMP : Conversation Creation");

            final Stage mainStage = (Stage) presence.getScene().getWindow();
            stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
                @Override
                public void handle(WindowEvent event) {
                    showConversations();
                }
            });

        } catch (IOException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void addRosterListener() {
        //when roster changes occur, the changes are tracked in here
        contactsManager.getRoster().addRosterListener(new RosterListener() {
            @Override
            public void entriesAdded(Collection<String> clctn) {
                java.util.Iterator<String> i = clctn.iterator();

                Task t = new Task() {
                    @Override
                    protected Object call() throws Exception {
                        return new Object();
                    }
                };

                t.setOnSucceeded(value -> {
                    showContacts();
                    while (i.hasNext()) {
                        String user = i.next();
                        if (contactsManager.getUserType(user).equals(ItemType.from)) {
                            Alert alert = new Alert(Alert.AlertType.INFORMATION);
                            alert.setTitle("Attention!");
                            alert.setHeaderText("Friend Request!");
                            alert.setContentText(
                                    "You have a new friend Request from " + user + ". Please check Contacts.");
                            alert.showAndWait();
                        }
                    }
                });
                Thread thread1 = new Thread(t);
                thread1.start();
            }

            @Override
            public void entriesUpdated(Collection<String> clctn) {
                Task t = new Task() {
                    @Override
                    protected Object call() throws Exception {
                        return new Object();
                    }
                };

                t.setOnSucceeded(value -> showContacts());
                Thread thread1 = new Thread(t);
                thread1.start();
            }

            @Override
            public void entriesDeleted(Collection<String> clctn) {
                Task t = new Task() {
                    @Override
                    protected Object call() throws Exception {
                        return new Object();
                    }
                };

                t.setOnSucceeded(value -> showContacts());
                Thread thread1 = new Thread(t);
                thread1.start();
            }

            @Override
            public void presenceChanged(Presence prsnc) {
                if (currentChat != null) {
                    if (prsnc.getFrom().contains(currentChat.getParticipant())) {
                        Task<String> t = new Task<String>() {
                            @Override
                            protected String call() throws Exception {
                                return prsnc.toString();
                            }
                        };
                        t.setOnSucceeded(value -> chatterPresence.setText(t.getValue()));

                        Thread thread = new Thread(t);
                        thread.start();
                    }

                }
                Task t = new Task() {
                    @Override
                    protected Object call() throws Exception {
                        return new Object();
                    }
                };

                t.setOnSucceeded(value -> showContacts());
                Thread thread1 = new Thread(t);
                thread1.start();
            }
        });
    }

    private void sendMessageGC() {
        //this method sends messages to the group chat
        if (currentmuc == null) {
            return;
        }
        if (message.getText().isEmpty()) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("IMP");
            alert.setHeaderText("Message is empty!");
            alert.setContentText("You can not send empty messages.");
            alert.showAndWait();
            return;
        }
        try {
            currentmuc.sendMessage(message.getText());
            message.setText("");
        } catch (XMPPException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private List<Message> getConversationHistory() {
        //get the group chat hostory from the server
        List<Message> msgList = new LinkedList<>();
        int i = 0;
        while (i < 100) {
            i++;
            try {
                Message msg = currentmuc.nextMessage(100);
                msgList.add(msg);
                paintConversationMessage(msg);
                if (msg == null) {
                    throw new NullPointerException();
                }
            } catch (NullPointerException e) {
                break;
            }

        }
        return msgList;
    }

    private void paintConversationMessage(Message msg) {
        //this method draws the recievied text message
        Task<HBox> recievedMessages = new Task<HBox>() {
            @Override
            protected HBox call() throws Exception {

                VBox vbox = new VBox(); //to add text
                String user = msg.getFrom();
                user = user.substring(user.indexOf("/") + 1, user.length());
                ImageView imageView = new ImageView(); //image
                imageView.setFitHeight(60);
                imageView.setFitWidth(50);
                VCard vcard = new VCard();
                try {
                    vcard.load(ConnectionManager.getConnectionManager().getXMPPConnection(),
                            user.concat(AppData.serviceNameAt));
                    if (vcard.getAvatar() != null) {
                        BufferedImage img = ImageIO.read(new ByteArrayInputStream(vcard.getAvatar()));
                        Image image = SwingFXUtils.toFXImage(img, null);
                        imageView.setImage(image);
                    } else {
                        Image defaultAvatar = new Image("resources/defaultAvatar.png", 50, 60, true, true);
                        imageView.setImage(defaultAvatar);
                    }
                } catch (XMPPException e) {
                    Image defaultAvatar = new Image("resources/defaultAvatar.png", 50, 60, true, true);
                    imageView.setImage(defaultAvatar);
                    System.out.println(e);
                }

                Label chatterName = new Label(user);
                chatterName.setDisable(true);

                //chat message
                BubbledLabel bbl = new BubbledLabel();
                bbl.setText(msg.getBody());
                bbl.setBackground(new Background(new BackgroundFill(Color.GAINSBORO, null, null)));

                vbox.getChildren().addAll(chatterName, bbl);
                vbox.setAlignment(Pos.CENTER_RIGHT);
                HBox hbox = new HBox();
                bbl.setBubbleSpec(BubbleSpec.FACE_LEFT_CENTER);
                hbox.getChildren().addAll(imageView, vbox);
                return hbox;
            }
        };

        recievedMessages.setOnSucceeded(event -> {
            chatList.getChildren().add(recievedMessages.getValue());

        });

        Thread t = new Thread(recievedMessages);
        //t.setDaemon(true);
        t.start();
        try {
            t.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
        Task t1 = new Task() {
            @Override
            protected Object call() throws Exception {
                Thread.sleep(500);
                return new Object();
            }
        };

        t1.setOnSucceeded(value -> scrollPane.setVvalue(scrollPane.getHmax()));

        Thread thread1 = new Thread(t1);
        thread1.start();
    }

    private void showExtraComButtons() {
        //shows the single chat only features
        extraComButtons.setVisible(true);
    }

    private void hideExtraComButtons() {
        //hide single chat only features in group chat
        extraComButtons.setVisible(false);
    }

    private void addConversationMessageListener() {
        //when conversation messages are gaththered, the messages are tracked in here
        if (currentmuc == null) {
            return;
        } else {
            currentmuc.addMessageListener(new PacketListener() {
                @Override
                public void processPacket(Packet packet) {

                    Message message = (Message) packet;

                    if (message.getFrom().contains(currentmuc.getRoom())) {
                        paintConversationMessage(message);
                    } else {
                        String conv = message.getFrom();
                        conv = conv.substring(0, conv.indexOf("@"));
                        String ms = message.getFrom();
                        ms = ms.substring(ms.indexOf("/") + 1, ms.length());
                        showNotifications(conv, ms + ": " + message.getBody());
                    }

                }
            });
        }
    }

    private void reloadConversationMessages(List<Message> msgList) {
        //reload the chat history from the second time
        //the chat is stored in the application and reload from the application
        Iterator i = msgList.iterator();
        while (i.hasNext()) {
            paintConversationMessage((Message) i.next());
        }
    }

    private void showNotifications(String chat, String message) {
        // a general method for view notifications -> windows notification
        if (!isnotifiable.isSelected()) {
            return;
        }
        URL url = System.class.getResource("/resources/LogoTransparent.png");
        java.awt.Image image = Toolkit.getDefaultToolkit().getImage(url);
        TrayIcon trayIcon = new TrayIcon(image, "Instant Messenger Plus");
        if (SystemTray.isSupported()) {
            SystemTray tray = SystemTray.getSystemTray();

            trayIcon.setImageAutoSize(true);
            try {
                tray.add(trayIcon);

            } catch (AWTException e) {
                System.err.println("TrayIcon could not be added.");
            }

            trayIcon.displayMessage("IMP: " + chat, message, TrayIcon.MessageType.INFO);
        }
    }

    private void addCallListener() {
        //system notifies the incomming calls
        List<JingleMediaManager> mediaManagers1 = new ArrayList<JingleMediaManager>();
        mediaManagers1.add(new JmfMediaManager(new BasicTransportManager()));
        final JingleManager jm1 = new JingleManager(connectionManager.getXMPPConnection(), mediaManagers1);

        jm1.addJingleSessionRequestListener(new JingleSessionRequestListener() {
            @Override
            public void sessionRequested(JingleSessionRequest jsr) {
                try {

                    System.out.println("Got one");
                    JingleSession session = jsr.accept();
                    session.startIncoming();

                    Task t = new Task() {
                        @Override
                        protected Object call() throws Exception {
                            return new Object();
                        }
                    };

                    t.setOnSucceeded(value -> {
                        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
                        alert.setTitle("Incoming Call");
                        alert.setHeaderText("You have an incomming call from " + session.getInitiator());

                        ButtonType buttonTpeYes = new ButtonType("Answer");
                        ButtonType buttonTypeNo = new ButtonType("Reject");
                        ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);

                        alert.getButtonTypes().setAll(buttonTpeYes, buttonTypeNo, buttonTypeCancel);

                        Optional<ButtonType> result = alert.showAndWait();
                        if (result.get() == buttonTpeYes) {
                            session.startIncoming(); //accept the call and answer the call

                        } else if (result.get() == buttonTypeNo) {
                            try {
                                session.terminate();
                            } catch (XMPPException ex) {
                                Alert alertError = new Alert(Alert.AlertType.ERROR);
                                alertError.setTitle("Error Occured");
                                alertError.setHeaderText("Call failure occured with " + ex.getMessage());
                            }
                        } else {
                            return;
                        }
                    });

                    Thread thread = new Thread(t);
                    thread.start();

                    Task t1 = new Task() {
                        @Override
                        protected Object call() throws Exception {
                            return new Object();
                        }
                    };

                    t1.setOnSucceeded(value -> {
                        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
                        alert.setTitle("Incoming Call");
                        alert.setHeaderText("Your Call  " + session.getInitiator());

                        ButtonType buttonTypeDisconnect = new ButtonType("Disconnect");

                        alert.getButtonTypes().setAll(buttonTypeDisconnect);

                        Optional<ButtonType> result = alert.showAndWait();
                        try {
                            session.terminate();
                        } catch (XMPPException ex) {
                        }
                    });

                    if (session.isFullyEstablished()) {
                        Thread thread1 = new Thread(t1);
                        thread.start();
                    }
                } catch (XMPPException ex) {
                    Logger.getLogger(CallViewController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    private void addMessageLimiter() {
        //this method limits the message that can be send over
        message.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(final ObservableValue<? extends String> ov, final String oldValue,
                    final String newValue) {
                if (message.getText().length() > 60) {
                    String s = message.getText().substring(0, 60);
                    message.setText(s);
                }
            }
        });
    }
}