var App = App || {};
App.Presenters = App.Presenters || {};

App.Presenters.CommentListPresenter = function(
    _,
    jQuery,
    util,
    promise,
    api,
    auth,
    topNavigationPresenter,
    messagePresenter) {

    var $el;
    var privileges;
    var templates = {};

    var post;
    var comments = [];

    function init(params, loaded) {
        $el = params.$target;
        post = params.post;
        comments = params.comments || [];

        privileges = {
            canListComments: auth.hasPrivilege(auth.privileges.listComments),
            canAddComments: auth.hasPrivilege(auth.privileges.addComments),
            canEditOwnComments: auth.hasPrivilege(auth.privileges.editOwnComments),
            canEditAllComments: auth.hasPrivilege(auth.privileges.editAllComments),
            canDeleteOwnComments: auth.hasPrivilege(auth.privileges.deleteOwnComments),
            canDeleteAllComments: auth.hasPrivilege(auth.privileges.deleteAllComments),
            canViewUsers: auth.hasPrivilege(auth.privileges.viewUsers),
            canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
        };

        promise.wait(
                util.promiseTemplate('comment-list'),
                util.promiseTemplate('comment-list-item'),
                util.promiseTemplate('comment-form'))
            .then(function(
                    commentListTemplate,
                    commentListItemTemplate,
                    commentFormTemplate)
                {
                    templates.commentList = commentListTemplate;
                    templates.commentListItem = commentListItemTemplate;
                    templates.commentForm = commentFormTemplate;

                    render();
                    loaded();

                    if (comments.length === 0) {
                        promise.wait(api.get('/comments/' + params.post.id))
                            .then(function(response) {
                                comments = response.json.comments;
                                render();
                            }).fail(function() {
                                console.log(arguments);
                            });
                    }
                })
            .fail(function() {
                console.log(arguments);
                loaded();
            });
    }

    function render() {
        $el.html(templates.commentList(
            _.extend(
                {
                    commentListItemTemplate: templates.commentListItem,
                    commentFormTemplate: templates.commentForm,
                    util: util,
                    comments: comments,
                    post: post,
                },
                privileges)));

        $el.find('.comment-add form button[type=submit]').click(function(e) { commentFormSubmitted(e, null); });
        renderComments(comments);
    }

    function renderComments(comments) {
        var $target = $el.find('.comments');
        var $targetList = $el.find('ul');

        if (comments.length > 0) {
            $target.show();
        } else {
            $target.hide();
        }

        $targetList.empty();
        _.each(comments, function(comment) {
            renderComment($targetList, comment);
        });
    }

    function renderComment($targetList, comment) {
        var $item = jQuery('<li>' + templates.commentListItem({
            comment: comment,
            util: util,
            canVote: auth.isLoggedIn(),
            canEditComment: auth.isLoggedIn(comment.user.name) ? privileges.canEditOwnComments : privileges.canEditAllComments,
            canDeleteComment: auth.isLoggedIn(comment.user.name) ? privileges.canDeleteOwnComments : privileges.canDeleteAllComments,
            canViewUsers: privileges.canViewUsers,
            canViewPosts: privileges.canViewPosts,
        }) + '</li>');
        util.loadImagesNicely($item.find('img'));
        $targetList.append($item);

        $item.find('a.edit').click(function(e) {
            e.preventDefault();
            editCommentStart($item, comment);
        });

        $item.find('a.delete').click(function(e) {
            e.preventDefault();
            deleteComment(comment);
        });

        $item.find('a.score-up').click(function(e) {
            e.preventDefault();
            score(comment, jQuery(this).hasClass('active') ? 0 : 1);
        });

        $item.find('a.score-down').click(function(e) {
            e.preventDefault();
            score(comment, jQuery(this).hasClass('active') ? 0 : -1);
        });
    }

    function commentFormSubmitted(e, comment) {
        e.preventDefault();
        var $button = jQuery(e.target);
        var $form = $button.parents('form');
        var sender = $button.val();
        if (sender === 'preview') {
            previewComment($form);
        } else {
            submitComment($form, comment);
        }
    }

    function previewComment($form) {
        var $preview = $form.find('.preview');
        $preview.slideUp('fast', function() {
            $preview.html(util.formatMarkdown($form.find('textarea').val()));
            $preview.slideDown('fast');
        });
    }

    function updateComment(comment) {
        comments = _.map(comments, function(c) { return c.id === comment.id ? comment : c; });
        render();
    }

    function addComment(comment) {
        comments.push(comment);
        render();
    }

    function submitComment($form, commentToEdit) {
        $form.find('.preview').slideUp();
        var $textarea = $form.find('textarea');

        var data = {text: $textarea.val()};
        var p;
        if (commentToEdit) {
            p = promise.wait(api.put('/comments/' + commentToEdit.id, data));
        } else {
            p = promise.wait(api.post('/comments/' + post.id, data));
        }

        p.then(function(response) {
            $textarea.val('');
            var comment = response.json.comment;

            if (commentToEdit) {
                $form.slideUp(function() {
                    $form.remove();
                });
                updateComment(comment);
            } else {
                addComment(comment);
            }
        }).fail(showGenericError);
    }

    function editCommentStart($item, comment) {
        if ($item.find('.comment-form').length > 0) {
            return;
        }
        var $form = jQuery(templates.commentForm({title: 'Edit comment', text: comment.text}));
        $item.find('.body').append($form);
        $item.find('form button[type=submit]').click(function(e) { commentFormSubmitted(e, comment); });
    }

    function deleteComment(comment) {
        if (!window.confirm('Are you sure you want to delete this comment?')) {
            return;
        }
        promise.wait(api.delete('/comments/' + comment.id))
            .then(function(response) {
                comments = _.filter(comments, function(c) { return c.id !== comment.id; });
                renderComments(comments);
            }).fail(showGenericError);
    }

    function score(comment, scoreValue) {
        promise.wait(api.post('/comments/' + comment.id + '/score', {score: scoreValue}))
            .then(function(response) {
                comment.score = parseInt(response.json.score);
                comment.ownScore = parseInt(response.json.ownScore);
                updateComment(comment);
            }).fail(showGenericError);
    }

    function showGenericError(response) {
        window.alert(response.json && response.json.error || response);
    }

    return {
        init: init,
        render: render,
    };

};

App.DI.register('commentListPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'auth', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.CommentListPresenter);