'use strict'

var urljoin = require('url-join'),
    config = require('./config'),
    helpers = require('./'),
    UsergridQuery = require('../lib/query'),
    UsergridEntity = require('../lib/entity'),
    UsergridAuth = require('../lib/auth'),
    util = require('util'),
    version = require('../package.json').version,
    ok = require('objectkit'),
    _ = require('lodash')

module.exports = {
    uri: function(client, options) {
        console.log(options.uuidOrName)
        return urljoin(
            client.baseUrl,
            client.orgId,
            client.appId,
            options.path || options.type,
            _.first([options.uuidOrName, options.uuid, options.name, ""].filter(_.isString))
        )
    },
    headers: function(client) {
        var headers = {
            'User-Agent': util.format("usergrid-nodejs/v%s", version)
        }
        var token
        if (ok(client).getIfExists('tempAuth') === UsergridAuth.NO_AUTH) {
            client.tempAuth = undefined
        } else {
            if (ok(client).getIfExists('tempAuth.isValid')) {
                // if ad-hoc authentication was set in the client, get the token and destroy the auth
                token = client.tempAuth.token
                client.tempAuth = undefined
            } else if (ok(client).getIfExists('currentUser.auth.isValid')) {
                // defaults to using the current user's token
                token = client.currentUser.auth.token
            } else if (ok(client).getIfExists('authFallback') === UsergridAuth.AuthFallback.APP && ok(client).getIfExists('appAuth.isValid')) {
                // if auth-fallback is set to APP request will make a call using the application token
                token = client.appAuth.token
            }
            if (token) {
                _.assign(headers, {
                    authorization: util.format("Bearer %s", token)
                })
            }
        }
        return headers
    },
    userLoginBody: function(options) {
        var body = {
            grant_type: 'password',
            password: options.password
        }
        if (options.tokenTtl) {
            body.ttl = options.tokenTtl
        }
        body[(options.username) ? "username" : "email"] = (options.username) ? options.username : options.email
        return body
    },
    appLoginBody: function(options) {
        var body = {
            grant_type: 'client_credentials',
            client_id: options.clientId,
            client_secret: options.clientSecret
        }
        if (options.tokenTtl) {
            body.ttl = options.tokenTtl
        }
        return body
    },
    GET: function(client, args) {

        /* GET supports the following constructor patterns:

        client.GET('type', 'uuidOrName', optionalCallback)
        client.GET('type', optionalCallback)
        client.GET(query, optionalCallback)
        client.GET({
            query: query, // takes precedence
            type: type, // required if query not defined
            uuid: uuid, // will be set to nameOrUuid on init (priority)
            name: name, // will be set to nameOrUuid on init (if no uuid specified)
            nameOrUuid: nameOrUuid // the definitive key for name or uuid
        }, optionalCallback)

        */

        var options = {
            client: client,
            method: 'GET',
            callback: helpers.cb(args)
        }

        // if a preformatted options argument passed, assign it to options
        if (_.isObject(args[0]) && !_.isFunction(args[0]) && args.length <= 2) {
            _.assign(options, args[0])
        }

        options.type = _.first([options.type, ok(args).getIfExists('0._type'), args[0]].filter(_.isString))

        options.query = _.first([options.query, args[0]].filter(function(property) {
            return (property instanceof UsergridQuery)
        }))
        options.uuidOrName = _.last([options.uuidOrName, options.uuid, options.name, args[1]].filter(function(property) {
            return (property)
        }))

        options.entity = _.first([options.entity, args[0]].filter(function(property) {
            return (property instanceof UsergridEntity)
        }))

        return options
    },
    PUT: function(client, args) {

        /* PUT supports the following constructor patterns:

        client.PUT('type', 'uuidOrName', bodyObject, optionalCallback)
        client.PUT('type', bodyObject, optionalCallback) // if no uuid, will create a new record
        client.PUT(bodyObjectOrEntity, optionalCallback) // if no uuid, will create a new record; must include type
        client.PUT(query, bodyObjectOrEntity, optionalCallback) // will update all entities matching query
        client.PUT(entity, optionalCallback)
        client.PUT({
            *entity = alias to body*
            query: query, // takes precedence over type/body
            type: type, // required if query not defined
            body: bodyObject or bodyObjectOrEntity, // if includes type, type will be inferred from body
            *uuid, name* = alias to nameOrUuid*
            nameOrUuid: nameOrUuid // the definitive key for name or uuid
        }, optionalCallback)

        */

        var options = {
            client: client,
            method: 'PUT',
            callback: helpers.cb(args)
        }

        // if a preformatted options argument passed, assign it to options
        if (_.isObject(args[0]) && !_.isFunction(args[0]) && args.length <= 2) {
            _.assign(options, args[0])
        }

        options.body = _.first([options.entity, options.body, args[2], args[1], args[0]].filter(function(property) {
            return _.isObject(property) && !_.isFunction(property) && !(property instanceof UsergridQuery)
        }))

        if (typeof options.body !== 'object') {
            throw new Error('"body" parameter is required when making a PUT request')
        }

        options.uuidOrName = _.first([options.nameOrUuid, options.uuid, options.name, options.body.uuid, args[2], args[1], args[0]].filter(_.isString))

        options.type = _.first([options.type, args[0]._type, options.body.type, args[0]].filter(_.isString))
        options.query = _.first([options.query, args[0]].filter(function(property) {
            return (property instanceof UsergridQuery)
        }))

        options.entity = _.first([options.entity, args[0]].filter(function(property) {
            return (property instanceof UsergridEntity)
        }))

        return options
    },
    POST: function(client, args) {

        /* POST supports the following constructor patterns:

        client.POST('type', bodyObjectOrArray, optionalCallback)
        client.POST(bodyObjectOrArray, optionalCallback) // must include type in body
        client.POST(entityOrEntities, optionalCallback)
        client.POST({
            *entity, entities = alias to body*
            type: type, // required
            body: bodyObjectOrArray or entityOrEntities, // if the first entity includes type, type will be inferred from body
        }, optionalCallback)

        */

        var options = {
            client: client,
            method: 'POST',
            callback: helpers.cb(args)
        }

        // if a preformatted options argument passed, assign it to options
        if (_.isObject(args[0]) && !_.isFunction(args[0]) && args.length <= 2) {
            _.assign(options, args[0])
        }

        options.body = _.first([options.entities, options.entity, options.body, args[1], args[0]].filter(function(property) {
            return _.isArray(property) && _.isObject(property[0]) && !_.isFunction(property[0]) || _.isObject(property) && !_.isFunction(property)
        }))

        if (typeof options.body !== 'object') {
            throw new Error('"body" parameter is required when making a POST request')
        }

        options.type = _.first([options.type, args[0], ok(options).getIfExists('body.0.type'), options.body.type].filter(_.isString))

        return options
    },
    DELETE: function(client, args) {

        /* DELETE supports the following constructor patterns:

        client.DELETE('type', 'uuidOrName', optionalCallback)
        client.DELETE(entity, optionalCallback) // must include type in body
        client.DELETE(query, optionalCallback)
        client.DELETE({
            *uuid, name* = alias to nameOrUuid*
            uuidOrName: uuidOrName,
            type: type, // required if query not defined
            query: query // takes precedence over type/uuid
        }, optionalCallback)

        */

        var options = {
            client: client,
            method: 'DELETE',
            callback: helpers.cb(args)
        }

        // if a preformatted options argument passed, assign it to options
        if (_.isObject(args[0]) && !_.isFunction(args[0]) && args.length <= 2) {
            _.assign(options, args[0])
        }

        options.type = _.first([options.type, ok(options).getIfExists('entity.type'), args[0]._type, args[0]].filter(_.isString))
        options.entity = _.first([options.entity, args[0]].filter(function(property) {
            return (property instanceof UsergridEntity)
        }))

        options.query = _.first([options.query, args[0]].filter(function(property) {
            return (property instanceof UsergridQuery)
        }))

        options.uuidOrName = _.first([options.uuidOrName, options.uuid, options.name, ok(options).getIfExists('entity.uuid'), args[1]].filter(_.isString))

        if (!_.isString(options.uuidOrName) && options.query === undefined) {
            throw new Error('"uuidOrName" parameter or "query" is required when making a DELETE request')
        }

        return options
    },
    connection: function(client, method, args) {

        /* connect supports the following constructor patterns:

        client.connect(entity, "relationship", toEntity);
        // POST entity.type/entity.uuid/"relationship"/toEntity.uuid

        client.connect("type", <uuidOrName>, "relationship", <toUuid>);
        // POST type/uuidOrName/relationship/toUuid

        client.connect("type", <uuidOrName>, "relationship", "toType", "toName");
        // POST type/uuidOrName/relationship/toType/toName

        client.connect({
            entity: { // or UsergridEntity
                type: "type", 
                uuidOrName: <uuidOrName>
            },
            relationship: "likes",
            to: { // or UsergridEntity
                "type": "(required if not using uuid)",
                "uuidOrName": <uuidOrName>,
                "name": "alias to uuidOrName" // if uuid not specified, requires "type"
                "uuid": "alias to uuidOrName" 
            }
        );

        disconnect supports the identical patters, but uses DELETE instead of POST; it is therefore a reference to this function

        */

        var options = {
            client: client,
            method: method,
            entity: {},
            to: {},
            callback: helpers.cb(args)
        }

        // if a preformatted options argument passed, assign it to options
        if (_.isObject(args[0]) && !_.isFunction(args[0]) && args.length <= 2) {
            _.assign(options, args[0])
        }

        // handle DELETE using "from" preposition
        if (_.isObject(options.from)) {
            options.to = options.from
        }

        // if an entity object or UsergridEntity instance is the first argument (source)
        if (_.isObject(args[0]) && !_.isFunction(args[0]) && _.isString(args[1])) {
            _.assign(options.entity, args[0])
            options.relationship = _.first([options.relationship, args[1]].filter(_.isString))
        }

        // if an entity object or UsergridEntity instance is the third argument (target)
        if (_.isObject(args[2]) && !_.isFunction(args[2])) {
            _.assign(options.to, args[2])
        }

        options.entity.uuidOrName = _.first([options.entity.uuidOrName, options.entity.uuid, options.entity.name, args[1]].filter(_.isString))
        if (!options.entity.type) {
            options.entity.type = _.first([options.entity.type, args[0]].filter(_.isString))
        }
        options.relationship = _.first([options.relationship, args[2]].filter(_.isString))

        if (_.isString(args[3]) && !_.isUuid(args[3]) && _.isString(args[4])) {
            options.to.type = args[3]
        } else if (_.isString(args[2]) && !_.isUuid(args[2]) && _.isString(args[3]) && _.isObject(args[0]) && !_.isFunction(args[0])) {
            options.to.type = args[2]
        }

        options.to.uuidOrName = _.first([options.to.uuidOrName, options.to.uuid, options.to.name, args[4], args[3], args[2]].filter(function(u) {
            return (_.isString(options.to.type) && _.isString(u) || _.isUuid(u))
        }))

        if (!_.isString(options.entity.uuidOrName)) {
            throw new Error('source entity "uuidOrName" is required when connecting or disconnecting entities')
        }

        if (!_.isString(options.to.uuidOrName)) {
            throw new Error('target entity "uuidOrName" is required when connecting or disconnecting entities')
        }

        if (!_.isString(options.to.type) && !_.isUuid(options.to.uuidOrName)) {
            throw new Error('target "type" (collection name) parameter is required connecting or disconnecting entities by name')
        }

        options.uri = urljoin(
            config.baseUrl,
            client.orgId,
            client.appId,
            _.isString(options.entity.type) ? options.entity.type : "",
            _.isString(options.entity.uuidOrName) ? options.entity.uuidOrName : "",
            options.relationship,
            _.isString(options.to.type) ? options.to.type : "",
            _.isString(options.to.uuidOrName) ? options.to.uuidOrName : ""
        )

        return options
    },
    getConnections: function(client, args) {
        /* getConnections supports the following constructor patterns:

        client.getConnections(direction, entity, "relationship");
        // GET OUT: /entity.type/entity.uuid/connections/relationship
        // GET IN: /entity.type/entity.uuid/connecting/relationship

        client.getConnections(direction, "type", "<uuidOrName>", "relationship");
        // GET OUT: /type/uuidOrName/connections/relationship
        // GET IN: /type/uuidOrName/connecting/relationship

        client.getConnections({
            type: "type", // or inferred, if second argument is an entity
            uuidOrName: "<uuidOrName>" // if entity not specified
            relationship: "relationship",
            direction: OUT or IN
        );
        // GET OUT: /entity.type/entity.uuid/connections/relationship
        // GET IN: /entity.type/entity.uuid/connecting/relationship

        */

        var options = {
            client: client,
            method: 'GET',
            callback: helpers.cb(args)
        }

        // if a preformatted options argument passed, assign it to options
        if (_.isObject(args[0]) && !_.isFunction(args[0]) && args.length <= 2) {
            _.assign(options, args[0])
        } else if (_.isObject(args[1]) && !_.isFunction(args[1])) {
            _.assign(options, args[1])
        }

        options.direction = _.first([options.direction, args[0]].filter(function(d) {
            return (d === "IN" || d === "OUT")
        }))

        options.relationship = _.first([options.relationship, args[3], args[2]].filter(_.isString))
        options.uuidOrName = _.first([options.uuidOrName, options.uuid, options.name, args[2]].filter(_.isString))
        options.type = _.first([options.type, args[1]].filter(_.isString))

        if (!_.isString(options.type)) {
            throw new Error('"type" (collection name) parameter is required when retrieving connections')
        }

        if (!_.isString(options.uuidOrName)) {
            throw new Error('target entity "uuidOrName" is required when retrieving connections')
        }

        options.uri = urljoin(
            config.baseUrl,
            client.orgId,
            client.appId,
            _.isString(options.type) ? options.type : "",
            _.isString(options.uuidOrName) ? options.uuidOrName : "",
            options.direction === "IN" ? "connecting" : "connections",
            options.relationship
        )

        return options
    }
}