'use strict';

const router = require('../router.js');
const api = require('../api.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, this._decorateSearchQuery(
                        parameters ? parameters.query : '')),
        ]).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 ?
                    '/post/' + ctx.parameters.id + '/edit' :
                    '/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));
            }
        }, errorMessage => {
            this._view = new EmptyView();
            this._view.showError(errorMessage);
        });
    }

    _decorateSearchQuery(text) {
        const browsingSettings = settings.get();
        let disabledSafety = [];
        for (let key of Object.keys(browsingSettings.listPosts)) {
            if (browsingSettings.listPosts[key] === false) {
                disabledSafety.push(key);
            }
        }
        if (disabledSafety.length) {
            text = `-rating:${disabledSafety.join(',')} ${text}`;
        }
        return text.trim();
    }

    _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();
            }, errorMessage => {
                this._view.sidebarControl.showError(errorMessage);
                this._view.sidebarControl.enableForm();
            });
    }

    _evtMergePost(e) {
        router.show('/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('/posts');
                ctx.controller.showSuccess('Post deleted.');
            }, errorMessage => {
                this._view.sidebarControl.showError(errorMessage);
                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();
            }, errorMessage => {
                this._view.sidebarControl.showError(errorMessage);
                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();
            }, errorMessage => {
                this._view.commentControl.showError(errorMessage);
                this._view.commentControl.enableForm();
            });
    }

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

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

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

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

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

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

module.exports = router => {
    router.enter('/post/:id/edit/:parameters(.*)?',
        (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
        (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/:parameters(.*)?',
        (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
        (ctx, next) => {
            // restore parameters from history state
            if (ctx.state.parameters) {
                Object.assign(ctx.parameters, ctx.state.parameters);
            }
            ctx.controller = new PostMainController(ctx, false);
        });
};