mesa = require 'mesa'

model = mesa
    .table('session')
    .attributes([
        'id'
        'hashed_secret'
        'session'
        'created'
        'modified'
    ])

module.exports = (getConnection, config = {}) ->

    config.cost ?= 10

    throw new Error 'cost has to be between 4 and 31' unless 4 <= config.cost <= 31

    model = model
        .connection(getConnection)


    getByIdAndSecret: (id, secret, cb) ->
        console.info 'postgres.getByIdAndSecret', id.substr(0,4), secret.substr(0,4)
        model
            .where(id: id)
            .where('hashed_secret = crypt(?, hashed_secret)', secret)
            .first (err, result) ->
                return cb err if err?
                return cb null, {} unless result?
                parsed = JSON.parse result.session
                cb null, parsed

    # this method uses two sql queries
    # the first is an update if the value is already existant
    # the other is used to introduce a new session item
    setByIdAndSecret: (id, secret, session, cb) ->
        console.log 'dao.session.setByIdAndSecret', id.substr(0,4), secret.substr(0,4), JSON.stringify(session)
        return cb err if err?
        stringified = JSON.stringify session
        model
            .where(id: id)
            .where('hashed_secret = crypt(?, hashed_secret)', secret)
            .update {session: stringified, modified: new Date()}, (err) ->
                return cb err if err?
                model.getConnection (err, connection, done) ->
                    return cb err if err?
                    sql = "INSERT INTO session (id, session, hashed_secret)
                        SELECT $1, $2, crypt($3, gen_salt('bf', $4)) WHERE NOT EXISTS
                            (SELECT 1 FROM session WHERE id=$1);"
                    params = [id, stringified, secret, config.cost]
                    connection.query sql, params, (err, result) ->
                        done?()
                        cb err, result

    deleteOlderThen: (date, cb) ->
        model.where(modified: $lt: date).delete cb
