'use strict'

var Usergrid = require('../usergrid'),
    helpers = require('../helpers'),
    ok = require('objectkit'),
    _ = require('lodash')

function updateEntityFromRemote(usergridResponse) {
    helpers.setWritable(this, ['uuid', 'name', 'type', 'created'])
    _.assign(this, usergridResponse.entity)
    helpers.setReadOnly(this, ['uuid', 'name', 'type', 'created'])
}

var UsergridEntity = function() {
    var self = this
    var args = helpers.args(arguments)

    if (args.length === 0) {
        throw new Error('A UsergridEntity object was initialized using an empty argument')
    }

    if (_.isObject(args[0])) {
        _.assign(self, args[0])
    } else {
        self.type = _.isString(args[0]) ? args[0] : undefined
        self.name = _.isString(args[1]) ? args[1] : undefined
    }
    
    if (!_.isString(self.type)) {
        throw new Error('"type" (or "collection") parameter is required when initializing a UsergridEntity object')
    }

    Object.defineProperty(self, 'tempAuth', {
        enumerable: false,
        configurable: true,
        writable: true
    })

    Object.defineProperty(self, 'isUser', {
        get: function() {
            return (self.type.toLowerCase() === 'user')
        }
    })

    Object.defineProperty(self, 'hasAsset', {
        get: function() {
            return ok(self).has(['file', 'file-metadata'])
        }
    })

    self.asset

    helpers.setReadOnly(self, ['uuid', 'name', 'type', 'created'])

    return self
}

UsergridEntity.prototype = {
    putProperty: function(key, value) {
        this[key] = value
    },
    putProperties: function(obj) {
        _.assign(this, obj)
    },
    removeProperty: function(key) {
        this.removeProperties([key])
    },
    removeProperties: function(keys) {
        var self = this
        keys.forEach(function(key) {
            delete self[key]
        })
    },
    insert: function(key, value, idx) {
        if (!_.isArray(this[key])) {
            this[key] = this[key] ? [this[key]] : []
        }
        this[key].splice.apply(this[key], [idx, 0].concat(value))
    },
    append: function(key, value) {
        this.insert(key, value, Number.MAX_SAFE_INTEGER)
    },
    prepend: function(key, value) {
        this.insert(key, value, 0)
    },
    pop: function(key) {
        if (_.isArray(this[key])) {
            this[key].pop()
        }
    },
    shift: function(key) {
        if (_.isArray(this[key])) {
            this[key].shift()
        }
    },
    reload: function() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        client.tempAuth = this.tempAuth
        this.tempAuth = undefined
        var callback = helpers.cb(args)
        client.GET(this, function(error, usergridResponse) {
            updateEntityFromRemote.call(this, usergridResponse)
            callback(error, usergridResponse, this)
        }.bind(this))
    },
    save: function() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        client.tempAuth = this.tempAuth
        this.tempAuth = undefined
        var callback = helpers.cb(args)
        client.PUT(this, function(error, usergridResponse) {
            updateEntityFromRemote.call(this, usergridResponse)
            callback(error, usergridResponse, this)
        }.bind(this))
    },
    remove: function() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        client.tempAuth = this.tempAuth
        this.tempAuth = undefined
        var callback = helpers.cb(args)
        client.DELETE(this, function(error, usergridResponse) {
            callback(error, usergridResponse, this)
        }.bind(this))
    },
    attachAsset: function(asset) {
        this.asset = asset
    },
    uploadAsset: function() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        var callback = helpers.cb(args)
        client.POST(this, this.asset, function(error, usergridResponse) {
            updateEntityFromRemote.call(this, usergridResponse)
            callback(error, usergridResponse, this) 
        }.bind(this))
    },
    downloadAsset: function() {},
    connect: function() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        client.tempAuth = this.tempAuth
        this.tempAuth = undefined
        args[0] = this
        return client.connect.apply(client, args)
    },
    disconnect: function() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        client.tempAuth = this.tempAuth
        this.tempAuth = undefined
        args[0] = this
        return client.disconnect.apply(client, args)
    },
    getConnections: function() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        client.tempAuth = this.tempAuth
        this.tempAuth = undefined
        args.shift()
        args.splice(1, 0, this)
        return client.getConnections.apply(client, args)
    },
    usingAuth: function(auth) {
        this.tempAuth = helpers.client.configureTempAuth(auth)
        return this
    }
}

module.exports = UsergridEntity