'use strict';

const unirest = require('unirest');
const validate = require('validate.js');
const _ = require('lodash');

const Common = require('./common');
const Builder = require('./actionbuilder')

function Voice(options) {
    this.options = options;
    this.ActionBuilder = Builder;
}

Voice.prototype.call = function (params) {

    let options = _.cloneDeep(params);
    let _self = this;

    // Validate params
    let _validateParams = function () {

        var constraints = {
            callTo: function (value) {

                if (validate.isEmpty(value)) {
                    return {
                        presence: {
                            message: 'is required'
                        }
                    };
                }
                if (!(/^(\+\d{1,3}\d{3,})(,\+\d{1,3}\d{3,})*$/).test(value)) {
                    return {
                        format: 'must not contain invalid callTo phone number'
                    };
                }

                return null;
            },
            callFrom: function (value) {

                if (validate.isEmpty(value)) {
                    return {
                        presence: {
                            message: 'is required'
                        }
                    };
                }
                return null;
            },

            clientRequestId: {
                isString: true,
            }
        };

        let error = validate(options, constraints);
        if (error) {
            // TODO should this be rejected by promise instead?

            var msg = "";
            for (var k in error) {
                msg += error[k] + "; ";
            }
            throw new Error(msg);
        }
    }

    _validateParams();

    return new Promise(function (resolve, reject) {

        const body = {
            username: _self.options.username,
            to: options.callTo,
            from: options.callFrom,
            clientRequestId: options.clientRequestId
        };

        const rq = unirest.post(Common.VOICE_URL + '/call');
        rq.headers({
            apikey: _self.options.apiKey,
            Accept: _self.options.format
        });

        rq.send(body);

        rq.end(function (resp) {
            if (resp.status === 200 || resp.status === 201) {
                // API returns CREATED on success
                resolve(resp.body);
            } else {
                reject(resp.body || resp.error);
            }
        });
    });
};

Voice.prototype.getNumQueuedCalls = function (params) {

    let options = _.cloneDeep(params);
    let _self = this;

    // Validate params
    let _validateParams = function () {

        var constraints = {
            phoneNumbers: function (value) {

                if (validate.isEmpty(value)) {
                    return {
                        presence: {
                            message: 'is required'
                        }
                    };
                }

                return null;
            }
        };

        let error = validate(options, constraints);
        if (error) {
            var msg = "";
            for (var k in error) {
                msg += error[k] + "; ";
            }
            throw new Error(msg);
        }
    }

    _validateParams();

    return new Promise(function (resolve, reject) {
        // list of phoneNumbers, comma separated
        let body = {
            username: _self.options.username,
            phoneNumbers: options.phoneNumbers
        };

        let rq = unirest.post(Common.VOICE_URL + '/queueStatus');
        rq.headers({
            apikey: _self.options.apiKey,
            Accept: _self.options.format
        });

        rq.send(body);

        rq.end(function (resp) {
            if (resp.status === 200 || resp.status === 201) {
                // API returns CREATED on success
                resolve(resp.body);
            } else {
                reject(resp.body || resp.error);
            }
        })
    });
};

Voice.prototype.uploadMediaFile = function (params) {
    let options = _.cloneDeep(params);
    let _self = this;

    // Validate params
    let _validateParams = function () {

        var constraints = {
            url: function (value) {
                if (validate.isEmpty(value)) {
                    return {
                        presence: {
                            message: 'is required'
                        }
                    };
                }

                if (!(/^https?\:\/\//).test(value)) {
                    return {
                        format: 'must contain a VALID URL (http(s)://...)'
                    }
                }

                return null;
            },
            phoneNumber: function (value) {

                if (validate.isEmpty(value)) {
                    return {
                        presence: {
                            message: 'is required'
                        }
                    };
                }

                return null;
            }
        };

        let error = validate(options, constraints);
        if (error) {
            var msg = "";
            for (var k in error) {
                msg += error[k] + "; ";
            }
            throw new Error(msg);
        }
    };

    _validateParams();

    return new Promise(function (resolve, reject) {
        let body = {
            username: _self.options.username,
            url: options.url,
            phoneNumber: options.phoneNumber
        };

        let rq = unirest.post(Common.VOICE_URL + '/mediaUpload');
        rq.headers({
            apikey: _self.options.apiKey,
            Accept: _self.options.format
        });

        rq.send(body);

        rq.end(function (resp) {
            if (resp.status === 201) {
                // API returns CREATED on success
                resolve(resp.body);
            } else {
                reject(resp.body || resp.error);
            }
        });
    });
};

module.exports = Voice;

@@ -746,32 +746,85 @@
               %7D%0A
+%0A                if (validate.isString(value)) %7B%0A    
                 
@@ -832,16 +832,18 @@
 f (!(/%5E(
+?:
 %5C+%5Cd%7B1,3
@@ -850,31 +850,18 @@
 %7D%5Cd%7B
-3,%7D)(,%5C+%5Cd%7B1,3%7D%5Cd%7B3,%7D)*
+5,%7D,?)%7B1,%7D
 $/).
@@ -887,32 +887,36 @@
                 
+    
 return %7B%0A       
@@ -924,32 +924,36 @@
                 
+    
 format: 'must no
@@ -989,18 +989,25 @@
 e number
-'%0A
+(s)'%0A    
         
@@ -1013,32 +1013,516 @@
              %7D;%0A
+                    %7D%0A                %7D%0A%0A                if (validate.isArray(value)) %7B%0A                    let foundInvalid = false;%0A                    value.forEach(function (phone) %7B%0A                        foundInvalid = !/%5E%5C+%5Cd%7B1,3%7D%5Cd%7B3,%7D$/.test(phone);%0A                    %7D);%0A                    if (foundInvalid) %7B%0A                        return %7B%0A                            format: %22must NOT contain invalid phone number(s)%22%0A                        %7D%0A                    %7D%0A
                 

Update voice callTo validator