_ = require 'underscore'

session = require '../../src/session'

storeStub =
    getByIdAndSecret: (id, secret, cb) -> cb null, null
    setByIdAndSecret: (id, secret, session, cb) -> cb null
    deleteOlderThen: (data, cb) -> cb null

session = session.store(storeStub)

module.exports =
    'send a sesion if their is none': (test) ->
        test.expect 6
        first = true
        req =
            cookies: {}
        res =
            setHeader: (key, data) ->
                test.equal 'Set-Cookie', key
                [key, value] = data.split '='
                if first
                    test.equal 'session_id', key
                    test.equal value.length, 32
                else
                    test.equal 'session_secret', key
                    test.equal value.length, 32
                first = false if first
        session.middleware() req, res, -> test.done()

    're-use session_id and session_secret': (test) ->
        first = true

        req =
            cookies:
                session_id: 'id'
                session_secret: 'secret'

        res = setHeader: (key, data) ->
            [key, value] = data.split '='
            test.equal 'id', value if first
            test.equal 'secret', value unless first
            first = false if first

        session.middleware() req, res, -> test.done()

    'options are different objects': (test) ->
        session1 = session
        session2 = session
            .domain('domain')

        test.notEqual session1.opts.domain, session2.opts.domain
        test.done()

    'options are send to middleware': (test) ->
        session
            .setCookieHandler((req, res, next) ->
                test.equal @opts['max-age'], 60
                test.equal @opts.domain, 'domain'
                test.equal @opts.path, '/path'
                test.equal @opts.expires, 'expire-date'
                test.equal @opts.httpOnly, false
                test.equal @opts.secure, true
                test.done()
            )
            .maxAge(60)
            .domain('domain')
            .path('/path')
            .expires('expire-date')
            .isHttpOnly(false)
            .isSecure(true)
            .middleware() ->

    'middleware can work with options': (test) ->
        req = cookies: {}
        res = setHeader: (key, data) ->
            [value, opt1, opt2] = elems = data.split '; '
            test.equal elems.length, 3
            test.ok opt1, 'missing option 1'
            test.ok opt2, 'missing option 2'
            [opt1Key, opt1Value] = opt1.split '='
            [opt2Key, opt2Value] = opt2.split '='
            test.equal opt1Key, 'Domain'
            test.equal opt1Value, 'example.org'

            test.equal opt2Key, 'Path'
            test.equal opt2Value, '/path'

        session
            .domain('example.org')
            .path('/path')
            .middleware() req, res, -> test.done()

    'sync middleware will fetch and set correct session data': (test) ->
        test.expect 7
        req = {cookies: {session_id: 'id', session_secret: 'secret'}}
        res = end: -> test.done()

        store =
            getByIdAndSecret: (id, secret, cb) ->
                test.equals id, 'id'
                test.equals secret, 'secret'
                cb null, {existing: 'bar'}
            setByIdAndSecret: (id, secret, session, cb) ->
                test.equals id, 'id'
                test.equals secret, 'secret'
                test.equals session.new, 'foo'
                test.equals session.existing, 'bar'
                cb null

        syncHandler = session.syncHandler.bind store: store
        syncHandler req, res, ->
            test.equals req.session.existing, 'bar'
            req.session.new = 'foo'
            res.end()

    'cleanup is executed with correct probability': (test) ->
        test.expect 1
        store =
            deleteOlderThen: (cutOfDate, cb) ->
                # sometimes this executes too slow
                test.ok new Date - cutOfDate < 5
                cb null
        cleanupHandler = session.cleanupHandler.bind {probability: 1, days: 0, store: store}
        cleanupHandler {}, {}, -> test.done()
