/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict'

var UsergridRequest = require('./request'),
    UsergridAsset = require('./asset'),
    helpers = require('../helpers'),
    _ = 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 cannot be initialized without passing one or more arguments')
    }

    var firstArg = args[0]
    if (_.isPlainObject(firstArg) || firstArg instanceof UsergridEntity ) {
        _.assign(self, args[0]);
    } else {
        if( !self.type ) {
            self.type = _.isString(args[0]) ? args[0] : undefined;
        }
        if( !self.name ) {
            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, 'asset', {
        enumerable: false,
        configurable: true,
        writable: true
    })

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

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

    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() {
        var args = helpers.args(arguments)
        var client = helpers.client.validate(args)
        var callback = helpers.cb(args)
        var self = this

        if (_.has(self,'asset.contentType')) {
            var options = {
                client: client,
                entity: self,
                type: this.type,
                method: 'GET',
                encoding: null,
                headers: {
                    "Accept": self.asset.contentType || _.first(args.filter(_.isString))
                }
            }
            options.uri = helpers.build.uri(client, options)
            return new UsergridRequest(options, function(error, usergridResponse) {
                if (usergridResponse.ok) {
                    self.attachAsset(new UsergridAsset(new Buffer(usergridResponse.body)))
                }
                callback(error, usergridResponse, self)
            })
        } else {
            callback({
                name: "asset_not_found",
                description: "The specified entity does not have a valid asset attached"
            })
        }
    },
    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