'use strict';

const router = require('../router.js');
const api = require('../api.js');
const uri = require('../util/uri.js');
const misc = require('../util/misc.js');
const settings = require('../models/settings.js');
const Comment = require('../models/comment.js');
const Post = require('../models/post.js');
const PostList = require('../models/post_list.js');
const PostMainView = require('../views/post_main_view.js');
const BasePostController = require('./base_post_controller.js');
const EmptyView = require('../views/empty_view.js');

class PostMainController extends BasePostController {
    constructor(ctx, editMode) {
        super(ctx);

        let parameters = ctx.parameters;
        Promise.all([
                Post.get(ctx.parameters.id),
                PostList.getAround(
                    ctx.parameters.id,
                    parameters ? parameters.query : null),
        ]).then(responses => {
            const [post, aroundResponse] = responses;

            // remove junk from query, but save it into history so that it can
            // be still accessed after history navigation / page refresh
            if (parameters.query) {
                ctx.state.parameters = parameters;
                const url = editMode ?
                    uri.formatClientLink('post', ctx.parameters.id, 'edit') :
                    uri.formatClientLink('post', ctx.parameters.id);
                router.replace(url, ctx.state, false);
            }

            this._post = post;
            this._view = new PostMainView({
                post: post,
                editMode: editMode,
                prevPostId: aroundResponse.prev ? aroundResponse.prev.id : null,
                nextPostId: aroundResponse.next ? aroundResponse.next.id : null,
                canEditPosts: api.hasPrivilege('posts:edit'),
                canDeletePosts: api.hasPrivilege('posts:delete'),
                canFeaturePosts: api.hasPrivilege('posts:feature'),
                canListComments: api.hasPrivilege('comments:list'),
                canCreateComments: api.hasPrivilege('comments:create'),
                parameters: parameters,
            });

            if (this._view.sidebarControl) {
                this._view.sidebarControl.addEventListener(
                    'favorite', e => this._evtFavoritePost(e));
                this._view.sidebarControl.addEventListener(
                    'unfavorite', e => this._evtUnfavoritePost(e));
                this._view.sidebarControl.addEventListener(
                    'score', e => this._evtScorePost(e));
                this._view.sidebarControl.addEventListener(
                    'fitModeChange', e => this._evtFitModeChange(e));
                this._view.sidebarControl.addEventListener(
                    'change', e => this._evtPostChange(e));
                this._view.sidebarControl.addEventListener(
                    'submit', e => this._evtUpdatePost(e));
                this._view.sidebarControl.addEventListener(
                    'feature', e => this._evtFeaturePost(e));
                this._view.sidebarControl.addEventListener(
                    'delete', e => this._evtDeletePost(e));
                this._view.sidebarControl.addEventListener(
                    'merge', e => this._evtMergePost(e));
            }

            if (this._view.commentControl) {
                this._view.commentControl.addEventListener(
                    'change', e => this._evtCommentChange(e));
                this._view.commentControl.addEventListener(
                    'submit', e => this._evtCreateComment(e));
            }

            if (this._view.commentListControl) {
                this._view.commentListControl.addEventListener(
                    'submit', e => this._evtUpdateComment(e));
                this._view.commentListControl.addEventListener(
                    'score', e => this._evtScoreComment(e));
                this._view.commentListControl.addEventListener(
                    'delete', e => this._evtDeleteComment(e));
            }
        }, error => {
            this._view = new EmptyView();
            this._view.showError(error.message);
        });
    }

    _evtFitModeChange(e) {
        const browsingSettings = settings.get();
        browsingSettings.fitMode = e.detail.mode;
        settings.save(browsingSettings);
    }

    _evtFeaturePost(e) {
        this._view.sidebarControl.disableForm();
        this._view.sidebarControl.clearMessages();
        e.detail.post.feature()
            .then(() => {
                this._view.sidebarControl.showSuccess('Post featured.');
                this._view.sidebarControl.enableForm();
            }, error => {
                this._view.sidebarControl.showError(error.message);
                this._view.sidebarControl.enableForm();
            });
    }

    _evtMergePost(e) {
        router.show(uri.formatClientLink('post', e.detail.post.id, 'merge'));
    }

    _evtDeletePost(e) {
        this._view.sidebarControl.disableForm();
        this._view.sidebarControl.clearMessages();
        e.detail.post.delete()
            .then(() => {
                misc.disableExitConfirmation();
                const ctx = router.show(uri.formatClientLink('posts'));
                ctx.controller.showSuccess('Post deleted.');
            }, error => {
                this._view.sidebarControl.showError(error.message);
                this._view.sidebarControl.enableForm();
            });
    }

    _evtUpdatePost(e) {
        this._view.sidebarControl.disableForm();
        this._view.sidebarControl.clearMessages();
        const post = e.detail.post;
        if (e.detail.tags !== undefined) {
            post.tags = e.detail.tags;
        }
        if (e.detail.safety !== undefined) {
            post.safety = e.detail.safety;
        }
        if (e.detail.flags !== undefined) {
            post.flags = e.detail.flags;
        }
        if (e.detail.relations !== undefined) {
            post.relations = e.detail.relations;
        }
        if (e.detail.content !== undefined) {
            post.newContent = e.detail.content;
        }
        if (e.detail.thumbnail !== undefined) {
            post.newThumbnail = e.detail.thumbnail;
        }
        post.save()
            .then(() => {
                this._view.sidebarControl.showSuccess('Post saved.');
                this._view.sidebarControl.enableForm();
                misc.disableExitConfirmation();
            }, error => {
                this._view.sidebarControl.showError(error.message);
                this._view.sidebarControl.enableForm();
            });
    }

    _evtPostChange(e) {
        misc.enableExitConfirmation();
    }

    _evtCommentChange(e) {
        misc.enableExitConfirmation();
    }

    _evtCreateComment(e) {
        this._view.commentControl.disableForm();
        const comment = Comment.create(this._post.id);
        comment.text = e.detail.text;
        comment.save()
            .then(() => {
                this._post.comments.add(comment);
                this._view.commentControl.exitEditMode();
                this._view.commentControl.enableForm();
                misc.disableExitConfirmation();
            }, error => {
                this._view.commentControl.showError(error.message);
                this._view.commentControl.enableForm();
            });
    }

    _evtUpdateComment(e) {
        // TODO: disable form
        e.detail.comment.text = e.detail.text;
        e.detail.comment.save()
            .catch(error => {
                e.detail.target.showError(error.message);
                // TODO: enable form
            });
    }

    _evtScoreComment(e) {
        e.detail.comment.setScore(e.detail.score)
            .catch(error => window.alert(error.message));
    }

    _evtDeleteComment(e) {
        e.detail.comment.delete()
            .catch(error => window.alert(error.message));
    }

    _evtScorePost(e) {
        if (!api.hasPrivilege('posts:score')) {
            return;
        }
        e.detail.post.setScore(e.detail.score)
            .catch(error => window.alert(error.message));
    }

    _evtFavoritePost(e) {
        if (!api.hasPrivilege('posts:favorite')) {
            return;
        }
        e.detail.post.addToFavorites()
            .catch(error => window.alert(error.message));
    }

    _evtUnfavoritePost(e) {
        if (!api.hasPrivilege('posts:favorite')) {
            return;
        }
        e.detail.post.removeFromFavorites()
            .catch(error => window.alert(error.message));
    }
}

module.exports = router => {
    router.enter(['post', ':id', 'edit'],
        (ctx, next) => {
            // restore parameters from history state
            if (ctx.state.parameters) {
                Object.assign(ctx.parameters, ctx.state.parameters);
            }
            ctx.controller = new PostMainController(ctx, true);
        });
    router.enter(
        ['post', ':id'],
        (ctx, next) => {
            // restore parameters from history state
            if (ctx.state.parameters) {
                Object.assign(ctx.parameters, ctx.state.parameters);
            }
            ctx.controller = new PostMainController(ctx, false);
        });
};