/*globals describe, before, beforeEach, afterEach, it*/
/*jshint expr:true*/
var testUtils       = require('../utils'),
    should          = require('should'),
    sinon           = require('sinon'),
    Promise         = require('bluebird'),
    _               = require('lodash'),

    // Stuff we are testing
    Models          = require('../../server/models'),
    permissions     = require('../../server/permissions'),
//    effectivePerms  = require('../../server/permissions/effective'),
//    context         = testUtils.context.owner,

    sandbox         = sinon.sandbox.create();

// TODO move to integrations or stub

describe('Permissions', function () {
    before(function (done) {
        Models.init().then(done).catch(done);
    });

    afterEach(function () {
        sandbox.restore();
    });

    beforeEach(function () {
        var permissions = _.map(testUtils.DataGenerator.Content.permissions, function (testPerm) {
            return testUtils.DataGenerator.forKnex.createPermission(testPerm);
        });

        sandbox.stub(Models.Permission, 'findAll', function () {
            return Promise.resolve(Models.Permissions.forge(permissions));
        });
    });

    it('can load an actions map from existing permissions', function (done) {
        permissions.init().then(function (actionsMap) {
            should.exist(actionsMap);

            actionsMap.edit.sort().should.eql(['post', 'tag', 'user', 'page'].sort());

            actionsMap.should.equal(permissions.actionsMap);

            done();
        }).catch(done);
    });

    // it('does not allow edit post without permission', function (done) {
    //    var fakePage = {
    //        id: 1
    //    };

    //    permissions.init()
    //        .then(function () {
    //            var canThisResult = permissions.canThis({id: 1});

    //            should.exist(canThisResult.edit);
    //            should.exist(canThisResult.edit.post);

    //            return canThisResult.edit.page(fakePage);
    //        })
    //        .then(function () {
    //            done(new Error('was able to edit post without permission'));
    //        }).catch(done);
    // });

    // it('allows edit post with permission', function (done) {
    //    var fakePost = {
    //        id: '1'
    //    };

    //    permissions.init()
    //        .then(function () {
    //            return Models.User.findOne({id: 1});
    //        })
    //        .then(function (foundUser) {
    //            var newPerm = new Models.Permission({
    //                name: 'test3 edit post',
    //                action_type: 'edit',
    //                object_type: 'post'
    //            });

    //            return newPerm.save(null, context).then(function () {
    //                return foundUser.permissions().attach(newPerm);
    //            });
    //        })
    //        .then(function () {
    //            return Models.User.findOne({id: 1}, { withRelated: ['permissions']});
    //        })
    //        .then(function (updatedUser) {

    //            // TODO: Verify updatedUser.related('permissions') has the permission?
    //            var canThisResult = permissions.canThis(updatedUser.id);

    //            should.exist(canThisResult.edit);
    //            should.exist(canThisResult.edit.post);

    //            return canThisResult.edit.post(fakePost);
    //        })
    //        .then(function () {
    //            done();
    //        }).catch(done);
    // });

    // it('can use permissible function on Model to allow something', function (done) {
    //    var testUser,
    //        permissibleStub = sandbox.stub(Models.Post, 'permissible', function () {
    //            return Promise.resolve();
    //        });

    //    testUtils.insertAuthorUser()
    //        .then(function () {
    //            return Models.User.findAll();
    //        })
    //        .then(function (foundUser) {
    //            testUser = foundUser.models[1];

    //            return permissions.canThis({user: testUser.id}).edit.post(123);
    //        })
    //        .then(function () {
    //            permissibleStub.restore();
    //            permissibleStub.calledWith(123, { user: testUser.id, app: null, internal: false })
    //                .should.equal(true);

    //            done();
    //        })
    //        .catch(function () {
    //            permissibleStub.restore();

    //            done(new Error('did not allow testUser'));
    //        });
    // });

    // it('can use permissible function on Model to forbid something', function (done) {
    //    var testUser,
    //        permissibleStub = sandbox.stub(Models.Post, 'permissible', function () {
    //            return Promise.reject();
    //        });

    //    testUtils.insertAuthorUser()
    //        .then(function () {
    //            return Models.User.findAll();
    //        })
    //        .then(function (foundUser) {
    //            testUser = foundUser.models[1];

    //            return permissions.canThis({user: testUser.id}).edit.post(123);
    //        })
    //        .then(function () {

    //            permissibleStub.restore();
    //            done(new Error('Allowed testUser to edit post'));
    //        })
    //        .catch(function () {
    //            permissibleStub.calledWith(123, { user: testUser.id, app: null, internal: false })
    //                .should.equal(true);
    //            permissibleStub.restore();
    //            done();
    //        });
    // });

    // it('can get effective user permissions', function (done) {
    //    effectivePerms.user(1).then(function (effectivePermissions) {
    //        should.exist(effectivePermissions);

    //        effectivePermissions.length.should.be.above(0);

    //        done();
    //    }).catch(done);
    // });

    // it('can check an apps effective permissions', function (done) {
    //    effectivePerms.app('Kudos')
    //        .then(function (effectivePermissions) {
    //            should.exist(effectivePermissions);

    //            effectivePermissions.length.should.be.above(0);

    //            done();
    //        })
    //        .catch(done);
    // });

    // it('does not allow an app to edit a post without permission', function (done) {
    //    // Change the author of the post so the author override doesn't affect the test
    //    Models.Post.edit({'author_id': 2}, _.extend(context, {id: 1}))
    //        .then(function (updatedPost) {
    //            // Add user permissions
    //            return Models.User.findOne({id: 1})
    //                .then(function (foundUser) {
    //                    var newPerm = new Models.Permission({
    //                        name: 'app test edit post',
    //                        action_type: 'edit',
    //                        object_type: 'post'
    //                    });

    //                    return newPerm.save(null, context).then(function () {
    //                        return foundUser.permissions().attach(newPerm).then(function () {
    //                            return Promise.all([updatedPost, foundUser]);
    //                        });
    //                    });
    //                });
    //        })
    //        .then(function (results) {
    //            var updatedPost = results[0],
    //                updatedUser = results[1];

    //            return permissions.canThis({ user: updatedUser.id })
    //                .edit
    //                .post(updatedPost.id)
    //                .then(function () {
    //                    return results;
    //                })
    //                .catch(function (err) {
    //                    /*jshint unused:false */
    //                    done(new Error('Did not allow user 1 to edit post 1'));
    //                });
    //        })
    //        .then(function (results) {
    //            var updatedPost = results[0],
    //                updatedUser = results[1];

    //            // Confirm app cannot edit it.
    //            return permissions.canThis({ app: 'Hemingway', user: updatedUser.id })
    //                .edit
    //                .post(updatedPost.id)
    //                .then(function () {
    //                    done(new Error('Allowed an edit of post 1'));
    //                }).catch(done);
    //        }).catch(done);
    // });

    // it('allows an app to edit a post with permission', function (done) {
    //    permissions.canThis({ app: 'Kudos', user: 1 })
    //        .edit
    //        .post(1)
    //        .then(function () {
    //            done();
    //        })
    //        .catch(function () {
    //            done(new Error('Did not allow an edit of post 1'));
    //        });
    // });

    // it('checks for null context passed and rejects', function (done) {
    //    permissions.canThis(undefined)
    //        .edit
    //        .post(1)
    //        .then(function () {
    //            done(new Error('Should not allow editing post'));
    //        })
    //        .catch(done);
    // });

    // it('allows \'internal\' to be passed for internal requests', function (done) {
    //    // Using tag here because post implements the custom permissible interface
    //    permissions.canThis('internal')
    //        .edit
    //        .tag(1)
    //        .then(function () {
    //            done();
    //        })
    //        .catch(function () {
    //            done(new Error('Should allow editing post with "internal"'));
    //        });
    // });

    // it('allows { internal: true } to be passed for internal requests', function (done) {
    //     // Using tag here because post implements the custom permissible interface
    //     permissions.canThis({internal: true})
    //        .edit
    //        .tag(1)
    //        .then(function () {
    //            done();
    //        })
    //        .catch(function () {
    //            done(new Error('Should allow editing post with { internal: true }'));
    //        });
    // });
});