/// <reference path="../../references.js" />

rwthapp.util.initNamespace("templates.das");

rwthapp.templates.das.channelDetails = (function () {
    var possiblePollAnswers = ["A", "B", "C", "D"];

    var nextIndex = 0;
    var timeout = null;
    var channelId = null;
    var pollingActive = false;
    var scrollToBottomOnRefresh = true;
    var channelPassword = "";
    var channelNeedsPassword = false;
    var pollActive = false;
    var channelName = "";
    var isChannelClosed = false;
    var templateName;
    var streamId;

    var channelPasswordStorage = new rwthapp.Storage("das.channelPasswords");

    var updateMessages = function () {
        // Avoid polling multiple times
        clearTimeout(timeout);

        var id = rwthapp.tokenManager.getUserId();
        if (streamId !== "") {
            id = streamId;
        }
        return rwthapp.connection.api.das.getMessages(channelId, id, nextIndex, channelPassword).then(function (data) {
            if (pollingActive) {
                if (data.length > 0) {
                    var receivedMessageFromLecturer = false;

                    for (var i = 0; i < data.length; i++) {
                        // Only text, picture and poll result messages are displayed
                        if (data[i].type === "text" || data[i].type === "picture" || data[i].type === "questionResult" || data[i].type === "broadcast") { // TODO broadcast should be removed from API
                            if ($('#div-' + data[i].messageID).length > 0) {
                                continue;
                            }

                            // Add additional attributes to message (handle picture messages and detect own messages)
                            transformMessageData(data[i]);

                            if (!data[i].myMessage) {
                                receivedMessageFromLecturer = true;
                            }

                            // Hide poll buttons if result was received
                            if (data[i].type === "questionResult") {
                                pollActive = false;
                                hidePollButtons();
                            }

                            $("#posts-div").append(rwthapp.templateRenderer.fetch("das.channelDetails.message", {
                                message: data[i]
                            }));
                        } else {
                            // Check if a poll is active
                            if (data[i].type === "question" && data[i].message === "open" && data[i].user === "system") {
                                pollActive = true;
                                showPollButtons();
                            }

                            // Check if supportchat was closed
                            if (data[i].type === "support" && data[i].message.indexOf('{"task":"supportClose"') > -1) {
                                disableSending();
                            }
                        }
                    }

                    // Get highest nextIndex from received data
                    updateNextIndex(data);

                    // Update unread message badge
                    updateNewMessageBadge();

                    // Use flot to render the results of surveys
                    renderQuestionResults();

                    // Scroll down (after image load if necessary) and update scrollfire to track last element
                    handleScrollingAfterAddingMessages();

                    // Perform postprocessing (fixing icons, removing waves effect) if necessary
                    rwthapp.templateRenderer.performPostprocessing();

                    // Notify user with vibration
                    if (receivedMessageFromLecturer) {
                        rwthapp.util.vibrate();
                    }
                }
            }
        }).catch(function (error) {
            // If polling failed due to missing password, prompt for password
            if (error.apiStatusCode === 33) {
                channelNeedsPassword = true;

                return promptForPassword().then(function (password) {
                    if (password !== undefined) {
                        channelPassword = password;
                        // Store password in localStorage
                        channelPasswordStorage.setItem(channelId, password);
                    } else {
                        // User did not click OK-Button, leave channel
                        rwthapp.navigator.goBack();
                    }
                });
            }
        }).then(function () {
            if (pollingActive) {
                // Resume polling
                clearTimeout(timeout);
                timeout = setTimeout(updateMessages, 5000);
            }
        });
    };

    var load = function (template, parameters) {
        channelId = parameters.channelId;
        nextIndex = 0;
        pollingActive = false;
        scrollToBottomOnRefresh = true;
        pollActive = false;
        channelName = "";
        channelNeedsPassword = false;
        templateName = template; 
        streamId = "";
        // Check if password was supplied as a parameter
        if (parameters.streamId !== undefined) {
            streamId = parameters.streamId;
        }
        if (parameters.password !== undefined) {
            channelPassword = parameters.password;
        } else {
            // Try to retrieve password from localStorage
            channelPassword = channelPasswordStorage.getItem(channelId, "");
        }

        return getChannelName(channelId).then(function (name) {
            channelName = name;
        }).then(function () {
            var id = rwthapp.tokenManager.getUserId();
            if (streamId !== "") {
                id = streamId;
            }
            return rwthapp.connection.api.das.getMessages(channelId, id, nextIndex, channelPassword);
        }).then(function (data) {
            var messagesToDisplay = [];
            var disable = false;
            // Transform data
            for (var i = 0; i < data.length; i++) {
                // Add additional attributes to message (handle picture messages and detect own messages)
                transformMessageData(data[i]);

                // Check if a poll is active
                if (data[i].type === "question" && data[i].message === "open" && data[i].user === "system") {
                    pollActive = true;
                }

                // Only display specific messages types
                if (data[i].type === "text" || data[i].type === "picture" || data[i].type === "questionResult" || data[i].type === "broadcast") { // TODO broadcast should be removed from API
                    messagesToDisplay.push(data[i]);
                }

                // TODO: move support channelId to config
                // Check if supportchat was closed
                if (channelId == 'e84ea4f1-3886-4ac0-857e-ffb79128d3fe' && data[i].type === "support" && data[i].message.indexOf('{"task":"supportClose"') > -1) {
                    disable = true;
                }
            }

            // Get highest nextIndex from received data
            updateNextIndex(data);

            return {
                template: template,
                parameters: {
                    messages: messagesToDisplay,
                    pollAnswers: possiblePollAnswers,
                    disableSending: disable
                },
                title: rwthapp.localization.getLocalizedString("titles.channelDetails"),
                subTitle: channelName
            };
        }).catch(function (error) {
            // If polling failed due to missing password, prompt in ready event
            if (error.apiStatusCode === 33) {
                channelNeedsPassword = true;

                return {
                    template: template,
                    parameters: {
                        pollAnswers: possiblePollAnswers
                    },
                    title: rwthapp.localization.getLocalizedString("titles.channelDetails"),
                    subTitle: channelName
                };
            }
            else if (error.apiStatusCode === 41) {
                
                isChannelClosed = true;

                return {
                    template: template,
                    parameters: {
                        channelClosed: rwthapp.localization.getLocalizedString("das.channelDetails.channelClosed"),
                    },
                    title: rwthapp.localization.getLocalizedString("titles.channelDetails"),
                    subTitle: channelName
                };
            }
            else {

                throw error;
            }
        });
    };

    var ready = function () {
        // TODO maybe reset nextIndex and clear div?

        if (isChannelClosed) {

            $('#reloadChannel').click(function () {

                rwthapp.navigator.refreshPage();
            });

            return;
        }

        // Scroll down (after image load if necessary) and update scrollfire to track last element
        handleScrollingAfterAddingMessages();

        // Use flot to render the results of surveys
        renderQuestionResults();

        if (pollActive) {
            showPollButtons();
        }

        $("#messageInput").on("keyup", function (e) {
            if (e.which === 13) {
                sendMessage();
            }
        });

        $("#messageInput").on("input", function () {
            if ($("#messageInput").val().length > 0) {
                showSendButton();
            } else {
                showPhotoButton();
            }
            // Perform postprocessing (fixing icons, removing waves effect) if necessary
            rwthapp.templateRenderer.performPostprocessing();
        });
        // Trigger once to show correct icon initially
        $("#messageInput").trigger("input");

        $("#submitButton").on("click", function () {
            // TODO same condition check in two places? (here and in input event)
            if ($("#messageInput").val().length > 0) {
                sendMessage();
            } else {
                rwthapp.cameraHelper.showPhotoDialog().then(function (photoData) {
                    if (photoData !== undefined) {
                        var id = rwthapp.tokenManager.getUserId();
                        if (streamId !== "") {
                            id = streamId;
                        }
                        rwthapp.connection.api.das.sendMessage(photoData.b64, channelId, "picture", id, channelPassword, photoData.angle).then(function () {
                            scrollDown();

                            // Poll messages to receive send message
                            updateMessages();
                        }).catch(function (error) {
                            // TODO error handling, maybe keep picture in memory and pass it as parameter to showPhotoDialog?
                            error.userfriendlyMessage = rwthapp.localization.getLocalizedString("das.channelDetails.sendingMessageFailed");
                            rwthapp.error.displayErrorMessage(error);
                        });
                    }
                });
            }
        });

        $("#gotoBottom").on("click", function () {
            scrollDown();
        });

        $(".pollButton").on("click", function () {
            var answer = $(this).val(); // TODO whitelist?

            $(".pollButton").prop('disabled', true);

            var id = rwthapp.tokenManager.getUserId();
            if (streamId !== "") {
                id = streamId;
            }
            rwthapp.connection.api.das.sendMessage(answer, channelId, "questionAnswer", id, channelPassword).then(function () {
                hidePollButtons();
            }).catch(function (error) {
                if (error.apiStatusCode === 39) {
                    // Poll already closed
                    pollActive = false;
                    hidePollButtons();

                    rwthapp.notifications.showDialog(rwthapp.localization.getLocalizedString("das.channelDetails.pollAlreadyClosed"));
                } else if (error.apiStatusCode === 40) {
                    // Already voted
                    pollActive = false;
                    hidePollButtons();

                    rwthapp.notifications.showDialog(rwthapp.localization.getLocalizedString("das.channelDetails.pollAlreadyAnswered"));
                } else {
                    error.userfriendlyMessage = rwthapp.localization.getLocalizedString("das.channelDetails.sendingMessageFailed");
                    rwthapp.error.displayErrorMessage(error);
                }
            }).then(function () {
                $(".pollButton").prop('disabled', false);
            });
        });

        // jQuery interprets events with a "." as namespaced event, so js event binding is used
        window.addEventListener('native.keyboardhide', keyboardHideListener, false);

        // Prompt for password if necessary or start polling if not
        if (channelNeedsPassword) {
            promptForPassword().then(function (password) {
                if (password !== undefined) {
                    channelPassword = password;
                    // Store password in localStorage
                    channelPasswordStorage.setItem(channelId, password);

                    resumePolling();
                } else {
                    // User did not click OK-Button, leave channel
                    rwthapp.navigator.goBack();
                }
            });
        } else {
            resumePolling();
        }
    };

    var pause = function () {
        pausePolling();
    };

    var resume = function () {
        resumePolling();
    };

    var exit = function () {

        isChannelClosed = false;

        pausePolling();

        $("#messageInput").off("keyup");
        $("#messageInput").off("input");
        $("#submitButton").off("click");
        $("#gotoBottom").off("click");

        window.removeEventListener('native.keyboardhide', keyboardHideListener, false);
    };

    var keyboardHideListener = function () {
        updateScrollFire();
        scrollDown();
    };

    var resumePolling = function () {
        pollingActive = true;
        clearTimeout(timeout);
        updateMessages();
    };

    var pausePolling = function () {
        pollingActive = false;
        clearTimeout(timeout);
    };

    var updateScrollFire = function () {
        $('.scrollfire').scrollfire('remove');
        $(".scrollfire").removeClass("scrollfire");
        $("#posts-div .das-message").last().addClass("scrollfire");

        $(".scrollfire").scrollfire({
            onBottomIn: function () {
                scrollToBottomOnRefresh = true;
                // Hide button to go to bottom
                $("#bottomBar").hide();

                $("#posts-div .new").removeClass("new");
                updateNewMessageBadge();
            },
            onBottomHidden: function () {
                scrollToBottomOnRefresh = false;
                // Show button to go to bottom
                $("#bottomBar").show();
            },
        });
    };

    var scrolledDown = function () {
        scrollToBottomOnRefresh = true;
        // Hide button to go to bottom
        $("#bottomBar").hide();

        $("#posts-div .new").removeClass("new");
        updateNewMessageBadge();
    };

    var scrollDown = function () {
        // Animated scrolling
        $("html, body").stop().animate({ scrollTop: $(document).height() - $(window).height() }, 400, "swing", function () {
            scrolledDown();
        });
    };

    var updateNextIndex = function (messages) {
        for (var i = 0; i < messages.length; i++) {
            if (messages[i].nextIndex > nextIndex) {
                nextIndex = messages[i].nextIndex;
            }
        }
    };

    var handleScrollingAfterAddingMessages = function () {
        // Handle image loading (replace tmp image after loading complete)
        $("img.loading").each(function (index, element) {
            if (element.complete) {
                $(element).removeClass("loading");
                
                if (scrollToBottomOnRefresh) {
                    // Scroll to bottom
                    scrollDown();
                }
            } else {
                $(element).on("load", function () {
                    $(element).removeClass("loading");
                    
                    if (scrollToBottomOnRefresh) {
                        // Scroll to bottom
                        scrollDown();
                    }
                });
            }
        });
        
        if (scrollToBottomOnRefresh) {
            // Scroll to bottom
            scrollDown();
        }  

        // Bind scrollfire to the last message div
        updateScrollFire();
    };

    var transformMessageData = function (message) {
        if (message.type === "picture") {
            message.isPicture = true;
            message.pictureUrl = rwthapp.connection.api.das.createPhotoURL(message.message);
        } else if (message.type === "questionResult") {
            message.isQuestionResult = true;
            // TODO crate flot data object and store as json
            var flotData = [];
            for (var i = 0; i < message.surveyResults.length; i++) {
                flotData.push([i, message.surveyResults[i].count]);
            }
            message.flotData = JSON.stringify(flotData);
        }

        message.myMessage = message.user === "student";
    };

    var sendMessage = function () {
        var message = $('#messageInput').val().trim();
        $("#messageInput").prop('disabled', true);
        $("#submitButton").prop('disabled', true);
        var id = rwthapp.tokenManager.getUserId();
        if (streamId !== "") {
            id = streamId;
        }
        rwthapp.connection.api.das.sendMessage(message, channelId, "text", id, channelPassword).then(function () {
            // Clear message
            $('#messageInput').val("");
            $("#messageInput").trigger("input"); // Update submit icon

            scrollDown();

            // Poll messages to receive send message
            updateMessages();
        }).catch(function (error) {
            // Handle error due to wrong password
            if (error.apiStatusCode === 33) {
                channelNeedsPassword = true;

                pausePolling();

                return promptForPassword().then(function (password) {
                    if (password !== undefined) {
                        channelPassword = password;
                        // Store password in localStorage
                        channelPasswordStorage.setItem(channelId, password);

                        // Try again (this time with password)
                        sendMessage();
                    }

                    resumePolling();
                });
            } else {
                error.userfriendlyMessage = rwthapp.localization.getLocalizedString("das.channelDetails.sendingMessageFailed");
                rwthapp.error.displayErrorMessage(error);
            }           
        }).then(function () {
            $("#messageInput").prop('disabled', false);
            $("#submitButton").prop('disabled', false);
        });
    };

    var showSendButton = function () {
        $("#submitIcon").html("send");
    };

    var showPhotoButton = function () {
        $("#submitIcon").html("photo_camera");
    };

    var updateNewMessageBadge = function () {
        var newMessages = $("#posts-div .new").length;
        if (newMessages > 0) {
            $("#newMessageCounter").show();
            $("#newMessageCounter").html(newMessages);
        } else {
            $("#newMessageCounter").hide();
        }
    };

    var promptForPassword = function () {
        return rwthapp.util.passwordPrompt(rwthapp.localization.getLocalizedString("das.channelDetails.passwordPrompt"));
    };

    var renderQuestionResults = function() {
        $(".poll-result.not-rendered").each(function(index, element) {
            var flotData = $(element).data("flotdata");

            // Dataset
            var data = [{
                data: flotData,
                bars: {
                    show: true,
                    align: 'center',
                    barWidth: 0.9
                },
                color: rwthapp.colors.orange()
            }];

            // Flot options
            var options = {
                xaxis: {
                    ticks: [[0, 'A'], [1, 'B'], [2, 'C'], [3, 'D']],
                    show: true
                },
                yaxis: {
                    tickDecimals: 0,
                    min: 0,
                    show: true
                }
            };

            $.plot($(element), data, options);
            $(element).removeClass("not-rendered");
        });
    };

    var showPollButtons = function () {
        $("#pollBar").show();
    };

    var hidePollButtons = function () {
        $("#pollBar").hide();
    };

    var disableSending = function () {
        $('#submitButton').attr('disabled', 'disabled');
        $('#messageInput').attr('disabled', 'disabled');
    }

    var getChannelName = function (channelId) {
        return rwthapp.connection.api.das.getChannelList().then(function (channels) {
            for (var i = 0; i < channels.length; i++) {
                if (channels[i].channelId === channelId) {
                    return channels[i].channelName;
                }
            }
            return "";
        });
    };

    return {
        load: load,
        ready: ready,
        pause: pause,
        resume: resume,
        exit: exit
    };
})();