archDB.factory('ChatMessage', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
    var ChatMessage = $resource(apiUrl('chat/messages/:messageId'), { messageId: '@id' }, methods);
    angular.extend(ChatMessage.prototype, _prototype);
    return ChatMessage;
}]);

archDB.factory('ChatChannel', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
    methods['leave'] = { method: 'POST', url: apiUrl('chat/channels/leave/:channelId'), params: { channelId: '@id' } };
    var ChatChannel = $resource(apiUrl('chat/channels/:channelId'), { channelId: '@id' }, methods);
    angular.extend(ChatChannel.prototype, _prototype);
    return ChatChannel;
}]);
archDB.controller('ChatChannelCtrl', ['$scope', 'ChatMessage', 'ErrorsHandler', 'socket', '$element', '$DesktopNotification', '$uibModal', 'ChatChannel', 'ngAudio', function ($scope, ChatMessage, ErrorsHandler, socket, $element, $DesktopNotification, $uibModal, ChatChannel, ngAudio) {

    var event_registered = false;

    $scope.messages = [];

    $scope.$on('popover-shown', function () {
        $scope.loading = true;
        $scope.load();

        _.each($scope.channels, function (el) {
            if (el === $scope.channel) {
                el.selected = true;
            }
            else {
                el.selected = false;
            }
        })
    });

    $scope.$on('popover-hidden', function () {
        $scope.channel.selected = false;
    })

    /**
     * Loads previous messages in this conversation.
     *
     * @return null
     */
    $scope.load = function () {
        ChatMessage.get({ channel: $scope.channel.id }, function (response) {
            $scope.loading = false;
            $scope.messages = response.data;
        }, ErrorsHandler);
    };

    /**
     * Registers the events listener that nodeJS will use
     * to broadcast messages to this channel.
     *
     * @return void
     */
    $scope.registerEvents = function () {
        if (event_registered == true) return false;

        // A new message received
        socket.on('new_message ' + $scope.channel.id, function (message) {
            message.own = false;
            $scope.messages.push(message);
            if (!$scope.channel.notifications) $scope.channel.notifications = 0;
            $scope.channel.notifications++;
            if (!$scope.channel.selected) {
                $DesktopNotification.show('#' + $scope.channel.tag + ' - ' + message.from.name, message.message);
                ngAudio.play('/audio/chat2.mp3');
            }
        });

        event_registered = true;
    };

    $scope.registerEvents();


    /**
     * Send a message in the channel
     *
     * @return void
     */
    $scope.send = function () {
        ChatMessage.save({ message: $scope.data.message, channel: $scope.channel.id, save_comment: $scope.data.save_comment }, function (response) {
            socket.emit('send_channel_message', { message: response, channel: $scope.channel.id });
            $scope.messages.push(response);
            $scope.data.message = '';
        }, ErrorsHandler);
    };

    /**
     * Display the channel settings modal
     *
     * @return void
     */
    $scope.showSettings = function () {
        var modalInstance = $uibModal.open({
            templateUrl: 'templates/modals/new-channel.html',
            controller: 'NewChannelCtrl',
            resolve: {
                channel: function () {
                    return $scope.channel;
                }
            }
        });

        modalInstance.result.then(function (response) {
            angular.extend($scope.channel, response || {});
        });
    };

    /**
     * Leave a private channel
     *
     * @return void
     */
    $scope.leave = function () {
        ChatChannel.leave({ id: $scope.channel.id }, function (response) {
            $scope.channels = _.reject($scope.channels, function (el) {
                return el === $scope.channel;
            });
        }, ErrorsHandler);
    };

    $scope.uploadFile = function () {
        var modalInstance = $uibModal.open({
            templateUrl: 'templates/modals/file-upload.html',
            controller: 'ChatFileUploadCtrl',
            resolve: {
                channel: function () {
                    return $scope.channel;
                }
            }
        });

        modalInstance.result.then(function () {
            $scope.load();
        });
    };

}]);
archDB.controller('ChatFileUploadCtrl', ['$scope', '$uibModalInstance', 'channel', function ($scope, $uibModalInstance, channel) {

    $scope.channel = channel;
    $scope.files = [];

    $scope.cancel = function () {
        $uibModalInstance.close();
    };

}]);
archDB.controller('ChatMainCtrl', ['$scope', 'socket', 'ChatChannel', 'ErrorsHandler', 'TimeLog', '$uibModal', '$idle', 'ThreeCXCall', function ($scope, socket, ChatChannel, ErrorsHandler, TimeLog, $uibModal, $idle, ThreeCXCall) {

    // Start watching for idle events...
    $idle.watch();

    $scope.channels = [];

    // Add makeCall function
    $scope.makeCall = function (number, type) {
        ThreeCXCall.makeCall(number, type);
    };

    $scope.loadChannels = function () {
        ChatChannel.get(function (response) {
            $scope.channels = response.data;
        }, ErrorsHandler);
    };

    $scope.loadUsers = function () {
        TimeLog.get({ userStatuses: true }, function (response) {
            $scope.users = _.reject(response.data, function (el) { return el.id == $scope.current_user.id; });
            $scope.refreshOnlineUsers();
            $scope.refreshIdleUsers();
        }, ErrorsHandler);
    };

    $scope.refreshOnlineUsers = function () {
        _.each($scope.users, function (el) {
            var user = _.find($scope.online_users, function (u) { return u == el.id; });
            el.online = user ? true : false;
        });
    };

    $scope.refreshIdleUsers = function () {
        _.each($scope.users, function (el) {
            var user = _.find($scope.idle_users, function (u) { return u == el.id; });
            el.idle = user ? true : false;
        });
    };

    $scope.getStatusClass = function (user) {
        if (!user.latest_time_log || user.latest_time_log.type == 'out') {
            return 'text-danger';
        }
        else if (user.latest_time_log.type == 'in' && user.latest_time_log.lunch == 1) {
            return 'text-lunch';
        }
        else if (user.latest_time_log.type == 'in') {
            return 'text-success';
        }

        return '';
    };

    $scope.loadChannels();
    $scope.loadUsers();

    $scope.openChannel = function (channel) {
        channel.notifications = 0; // Reset the notifications
    };

    $scope.openChannel = function (channel) {
        channel.notifications = 0; // Reset the notifications
    };

    $scope.openPrivate = function (user) {
        user.notifications = 0; // Reset the notifications
    };

    $scope.newChannel = function () {
        var modalInstance = $uibModal.open({
            templateUrl: 'templates/modals/new-channel.html',
            controller: 'NewChannelCtrl',
            resolve: {
                channel: function () { return null; }
            }
        });

        modalInstance.result.then(function (response) {
            $scope.channels.push(response);
        });
    };

    $scope.$on('$idleStart', function () {
        socket.emit('idle');
    });

    $scope.$on('$idleEnd', function () {
        socket.emit('idleEnd');
    });

    socket.on('idle', function (id) {
        var user = _.find($scope.users, function (u) { return u.id == id; });
        if (user) user.idle = true;
    });

    socket.on('idleEnd', function (id) {
        var user = _.find($scope.users, function (u) { return u.id == id; });
        if (user) user.idle = false;
    });

    socket.on('online_users', function (users) {
        $scope.online_users = users;
        $scope.refreshOnlineUsers();
    });

    socket.on('idle_users', function (users) {
        $scope.idle_users = users;
        $scope.refreshIdleUsers();
    });

    socket.on('user_connected', function (id) {
        var user = _.find($scope.users, function (u) { return u.id == id; });
        if (user) user.online = true;
    });

    socket.on('user_disconnected', function (id) {
        var user = _.find($scope.users, function (u) { return u.id == id; });
        if (user) user.online = false;
    });

}]);
archDB.controller('ChatPrivateCtrl', ['$scope', 'ChatMessage', 'ErrorsHandler', 'socket', '$element', '$DesktopNotification', '$uibModal', 'ngAudio', function ($scope, ChatMessage, ErrorsHandler, socket, $element, $DesktopNotification, $uibModal, ngAudio) {

    var event_registered = false;

    $scope.messages = [];
    $scope.data = {};
    $scope.direct_message = true;

    $scope.$on('popover-shown', function () {
        $scope.loading = true;
        $scope.load();

        _.each($scope.users, function (el) {
            if (el === $scope.user)
                el.selected = true;
            else
                el.selected = false;
        })
    });

    $scope.$on('popover-hidden', function () {
        $scope.user.selected = false;
    });

    /**
     * Loads previous messages in this conversation.
     *
     * @return null
     */
    $scope.load = function () {
        ChatMessage.get({ chat_user: $scope.user.id }, function (response) {
            $scope.loading = false;
            $scope.thread_id = response.thread_id;
            $scope.messages = response.data;
            $scope.registerEvents();
        }, ErrorsHandler);
    };

    $scope.registerEvents = function () {
        if (event_registered == true) return false;

        if (!$scope.thread_id) $scope.thread_id = ($scope.user.id < $scope.current_user.id) ? $scope.user.id + '-' + $scope.current_user.id : $scope.current_user.id + '-' + $scope.user.id;

        // A new message received
        socket.on('new_message ' + $scope.thread_id, function (message) {
            message.own = false;
            $scope.messages.push(message);
            if (!$scope.user.notifications) $scope.user.notifications = 0;
            $scope.user.notifications++;
            if (!$scope.user.selected) {
                $DesktopNotification.show($scope.user.name, message.message);
                ngAudio.play('/audio/chat2.mp3');
            }
        });

        event_registered = true;
    };

    $scope.$watch('current_user', function (user) {
        if (user) $scope.registerEvents();
    });

    $scope.send = function () {
        $scope.data.to = $scope.user.id;

        ChatMessage.save($scope.data, function (response) {
            socket.emit('send_message', { message: response, thread_id: response.thread_id, to: $scope.user.id });
            $scope.messages.push(response);
            $scope.data.message = '';
        }, ErrorsHandler);
    };

    $scope.uploadFile = function () {
        var modalInstance = $uibModal.open({
            templateUrl: 'templates/modals/file-upload.html',
            controller: 'ChatFileUploadCtrl',
            resolve: {
                channel: function () {
                    return { id: $scope.thread_id };
                }
            }
        });

        modalInstance.result.then(function () {
            $scope.load();
        });
    };

}]);
archDB.controller('NewChannelCtrl', ['$scope', 'User', '$uibModalInstance', 'ErrorsHandler', 'ChatChannel', 'channel', function ($scope, User, $uibModalInstance, ErrorsHandler, ChatChannel, channel) {

    $scope.data = channel || {};

    $scope.select2Options = {
        allowClear: true,
        minimumInputLength: 1,
        placeholder: 'Search for users',
        query: function (options) {

            User.get({ q: options.term, page: options.page, active: true }, function (response) {
                options.callback({
                    more: response.current_page < response.last_page,
                    results: response.data
                });
            });

        },
        formatResult: function (obj, container, query) {
            return obj.name;
        },
        formatSelection: function (obj) {
            return obj.name;
        }
    };

    $scope.save = function () {
        if ($scope.data.id) {
            ChatChannel.update($scope.data, function (response) {
                $uibModalInstance.close(response);
            }, ErrorsHandler);
        }
        else {
            ChatChannel.save($scope.data, function (response) {
                $uibModalInstance.close(response);
            }, ErrorsHandler);
        }
    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };

}]);
archDB.directive('chatScroll', ['$timeout', function ($timeout) {
    return {
        restrict: 'AE',
        link: function (scope, element, attrs) {
            scope.scrollToBottom = function () {
                $timeout(function () {
                    element.animate({ scrollTop: element[0].scrollHeight }, 300);
                    element.siblings('form').find('input:first').focus();
                }, 50);
            };

            scope.$watch('messages', scope.scrollToBottom, true);
            scope.$on('popover-shown', scope.scrollToBottom);
        }
    };
}]);
archDB.directive('chatTab', [function () {
    return {
        restrict: 'A',
        scope: {
            user: '=',
            closeTab: '&'
        },
        transclude: true,
        controller: ['$scope', 'ErrorsHandler', 'ChatMessage', 'socket', '$element', '$timeout', function ($scope, ErrorsHandler, ChatMessage, socket, $element, $timeout) {

            // Fetch previous messages
            $scope.messages = [];
            $scope.thread_id = null;

            var event_registered = false;

            $scope.$watch('messages', function () {
                $scope.scrollToBottom();
            }, true);

            /**
             * Loads previous messages in this conversation.
             *
             * @return null
             */
            $scope.load = function () {
                ChatMessage.get({ chat_user: $scope.user.id }, function (response) {
                    $scope.messages = response.data;
                    $scope.thread_id = response.thread_id;
                    $scope.registerEvents(response.thread_id);
                }, ErrorsHandler);
            };

            $scope.registerEvents = function (thread_id) {
                if (event_registered == true) return false;

                // A new message received
                socket.on('new_message ' + thread_id, function (message) {
                    $scope.messages.push(message);
                });

                event_registered = true;
            };

            $scope.load();

            /**
             * Send a message to a user
             *
             * @return null
             */
            $scope.send = function () {
                ChatMessage.save({ message: $scope.message, to: $scope.user.id }, function (response) {
                    socket.emit('send_message', { message: response, to: $scope.user.id, thread_id: $scope.thread_id });
                    $scope.messages.push(response);
                    $scope.message = '';
                }, ErrorsHandler);
            };

            $scope.scrollToBottom = function () {
                var el = $element.find('.chat-messages');
                $timeout(function () {
                    el.animate({ scrollTop: el[0].scrollHeight }, 300);
                }, 50);
            };

        }],
        link: function ($scope, $element, $attrs, ctrl, transclude) {

            transclude($scope, function (clone) {
                $element.append(clone);
            });

        }
    };
}]);