'use strict';

/* eslint-env node, mocha */
const chai = require('chai');
const sinon = require('sinon');
const chaiSinon = require('chai-sinon');
const sinonChaiInOrder = require('sinon-chai-in-order').default;
const Promise = require('bluebird');
const bot = require('../../src/bot');
const CacheMiddleware = require('../../src/middleware/CacheMiddleware');

const expect = chai.expect;
chai.use(chaiSinon);
chai.use(sinonChaiInOrder);

describe('CacheMiddleware class', () => {
    it(`returns the original parameter for non-used functions`, () => {
        const middleware = new CacheMiddleware();
        const response = {
            should: {
                be: {
                    the: {
                        same: 'object'
                    }
                }
            }
        };

        expect(middleware.onReplyPosted(response)).to.deep.equal(response);
    });

    it('returns the original object when nothing has been cached', () => {
        const middleware = new CacheMiddleware();
        bot.cache = {
            get: sinon.stub().returns(Promise.resolve(undefined))
        };
        const response = {
            request: {
                params: { }
            }
        };

        return middleware.onCommand(response).then(result => {
            expect(result).to.deep.equal(response);
            expect(bot.cache.get).to.have.been.called;
        });
    });

    it('returns the original object plus text from cache', () => {
        const text = 'some cached text';
        const middleware = new CacheMiddleware();
        bot.cache = {
            get: sinon.stub().returns(Promise.resolve(text))
        };
        const response = {
            request: {
                params: {
                    some: 'param'
                }
            }
        };

        return middleware.onCommand(response).then(result => {
            expect(result.reply).to.equal(text);
            expect(bot.cache.get).to.have.been.called;
        });
    });

    it('caches the result', () => {
        const middleware = new CacheMiddleware({
            duration: 10
        });
        bot.cache = {
            set: sinon.expectation.create('set').returns(Promise.resolve())
        };
        const response = {
            request: {
                params: { }
            },
            reply: 'some text to cache'
        };

        return middleware.onReplyConstructed(response).then(() => {
            expect(bot.cache.set.args[0][2]).to.equal(middleware.options.duration);
            expect(bot.cache.set.args[0][3]).to.equal(response.reply);
        });
    });

    it('caches the result with param uniqueness', () => {
        const middleware = new CacheMiddleware({
            unique_params: true
        });
        bot.cache = {
            get: sinon.expectation.create('get').twice().returns(Promise.resolve()),
            set: sinon.stub().returns(Promise.resolve())
        };
        const response1 = {
            request: {
                params: { }
            },
            reply: 'some text to cache'
        };
        const response2 = {
            request: {
                params: {
                    some: 'param'
                }
            },
            reply: 'some text to cache'
        };

        return middleware.onReplyConstructed(response1).then(() => {
            return Promise.all([
                middleware.onCommand(response1),
                middleware.onCommand(response2)
            ]).then(() => {
                expect(bot.cache.get.args[0][1]).to.not.equal(bot.cache.get.args[1][1]);
            });
        });
    });

    it('caches the result with user uniqueness', () => {
        const middleware = new CacheMiddleware({
            unique_params: false,
            unique_user: true
        });
        bot.cache = {
            get: sinon.expectation.create('get').twice().returns(Promise.resolve()),
            set: sinon.stub().create('set').returns(Promise.resolve())
        };
        const response1 = {
            request: {
                message: {
                    author: {
                        id: '1'
                    }
                }
            },
            reply: 'some text to cache'
        };
        const response2 = {
            request: {
                message: {
                    author: {
                        id: '2'
                    }
                }
            },
            reply: 'some text to cache'
        };

        return middleware.onReplyConstructed(response1).then(() => {
            return Promise.all([
                middleware.onCommand(response1),
                middleware.onCommand(response2)
            ]).then(() => {
                expect(bot.cache.get.args[0][1]).to.not.equal(bot.cache.get.args[1][1]);
            });
        });
    });
});

@@ -2133,32 +2133,90 @@
   bot.cache = %7B%0A
+            get: sinon.stub().returns(Promise.resolve()),%0A
             set:
@@ -2267,32 +2267,32 @@
 mise.resolve())%0A
-
         %7D;%0A     
@@ -2890,33 +2890,34 @@
 .create('get').t
-w
+hr
 ice().returns(Pr
@@ -3604,33 +3604,33 @@
 .cache.get.args%5B
-0
+1
 %5D%5B1%5D).to.not.equ
@@ -3643,33 +3643,33 @@
 .cache.get.args%5B
-1
+2
 %5D%5B1%5D);%0A         
@@ -3950,17 +3950,18 @@
 'get').t
-w
+hr
 ice().re
@@ -4830,17 +4830,17 @@
 et.args%5B
-0
+1
 %5D%5B1%5D).to
@@ -4865,25 +4865,25 @@
 he.get.args%5B
-1
+2
 %5D%5B1%5D);%0A     

Fix tests