Source: plugins/wtapi.queues.js

import WTAPI from '../wtapi'
import {JSJaCIQ} from '../jsjac';


/**
 * Plugin provides a possibility to work with Queues events
 *
 * @version 1.0.0
 */

var NS_QUEUES = "urn:wildix:queues";

/**
 * Constructor for Queues plugin.
 * Instance will be created each time when new WTAPI instance is created. <br />
 * Plugin could be accessible thought WTAPI with <b>queues</b> property.
 *
 * @memberof WTAPI
 * @alias WTAPI.QueuesPlugin
 * @augments WTAPI.Observer
 * @public
 * @constructor
 */
function QueuesPlugin(wtapi) {
    this._queues = [];
    this._subscribed = false;
    this._wtapi = wtapi;
    this._wtapi.registerHandler("message", this._handleMessage, this, 10);
    this._wtapi.addListener("connected", this._onConnected, this);
    this._wtapi.addListener("disconnected", this._onDisconnected, this);

    this._messageHandlers = [
        this._handleMessageQueueAdd,
        this._handleMessageQueueRemove,
        this._handleMessageMemberAdd,
        this._handleMessageMemberUpdate,
        this._handleMessageMemberRemove,
        this._handleMessageMemberCallAdd,
        this._handleMessageMemberCallRemove,
        this._handleMessageUserJoin,
        this._handleMessageUserLeave
    ];

    // Initialize supper
    WTAPI.Observable.call(this);
}

QueuesPlugin.prototype = Object.create(WTAPI.Observable.prototype);

// ============================================================
// Public events
// ============================================================

// ============================================================
// Public functions
// ============================================================


/**
 * @callback QueueActionCallback
 * @param {string} error An error message, null when operation is successful
 */

/**
 * Subscribe to a queue events
 *
 * @param callback
 */
QueuesPlugin.prototype.subscribe = function (callback) {
    if (this._subscribed) {
        return;
    }

    this._subscribed = true;

    var scope = arguments[1] || this;
    var self = this;
    var packet = this._createSubscribePacket();
    var handlers = {
        result_handler: function (iq) {
            self._handleSubscribeResponse(iq, callback, scope);
        }
    }

    this._wtapi.getConnection().sendIQ(packet, handlers);
}

/**
 * Checks whether WTAPI is Subscribed to Queues events
 *
 * @returns {boolean}
 */
QueuesPlugin.prototype.isSubscribed = function () {
    return this._subscribed;
}

/**
 * Removes subscription from a queues events
 *
 * @param {function} callback
 */
QueuesPlugin.prototype.unsubscribe = function (callback) {
    var scope = arguments[1] || this;
    var self = this;
    var packet = this._createUnsubscribePacket();
    var handlers = {
        result_handler: function (iq) {
            self._handleUnsubscribeResponse(iq, callback, scope);
        }
    }

    this._wtapi.getConnection().sendIQ(packet, handlers);
}

/**
 * Add member to a specified queue.
 * When member will be added he will have a Dynamic membership.
 *
 * @param {Queue} queue
 * @param {String} extension
 * @param {QueueActionCallback} callback
 */
QueuesPlugin.prototype.add = function (queue, extension, callback) {
    var scope = arguments[3] || this;
    var packet = this._createAddPacket(queue, extension);
    var handlers = this._createIqHandler(callback, scope);
    this._wtapi.getConnection().sendIQ(packet, handlers);
}

/**
 * Remove a Dynamic member from a queue
 *
 * @param {Queue} queue
 * @param {QueueMember} member
 * @param {QueueActionCallback} callback
 */
QueuesPlugin.prototype.remove = function (queue, member, callback) {
    var scope = arguments[3] || this;
    var packet = this._createRemovePacket(queue, member);
    var handlers = this._createIqHandler(callback, scope);
    this._wtapi.getConnection().sendIQ(packet, handlers);
}

/**
 * Pause a member in queue.
 * When user is on pause, he wouldn't receive a new calls from that queue.
 *
 * @param {Queue} queue
 * @param {QueueMember} member
 * @param {QueueActionCallback} callback
 */
QueuesPlugin.prototype.pause = function (queue, member, callback) {
    var scope = arguments[3] || this;
    var packet = this._createPausePacket(queue, member);
    var handlers = this._createIqHandler(callback, scope);
    this._wtapi.getConnection().sendIQ(packet, handlers);
}

/**
 * Resume a member from pause
 *
 * @param {Queue} queue
 * @param {QueueMember} member
 * @param {QueueActionCallback} callback
 */
QueuesPlugin.prototype.resume = function (queue, member, callback) {
    var scope = arguments[3] || this;
    var packet = this._createResumePacket(queue, member);
    var handlers = this._createIqHandler(callback, scope);
    this._wtapi.getConnection().sendIQ(packet, handlers);
}


/**
 * Returns a list of available queues.
 *
 * @access public
 * @returns {Array}
 */
QueuesPlugin.prototype.getQueues = function () {
    return this._queues;
}

/**
 * Returns a list of available queues.
 *
 * @param {String} id A Queue ID
 * @access public
 * @returns {Queue} A Queue Object or null if queue is not found.
 */
QueuesPlugin.prototype.getQueue = function (id) {
    for (var i = 0; i < this._queues.length; i++) {
        if (this._queues[i].getId() == id) {
            return this._queues[i];
        }
    }

    return null;
}


// ============================================================
// Plugin callbacks
// ============================================================

/**
 * @private
 */
QueuesPlugin.prototype._onConnected = function () {
    if (this._subscribed) {
        this._subscribed = false;
        this.subscribe();
    }
}

/**
 * @private
 */
QueuesPlugin.prototype._onDisconnected = function () {
    for (var i = 0; i < this._queues.length; i++) {
        this._fire("queue_removed", this._queues[i]);
    }

    this._queues = [];
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessage = function (message) {
    var event = message.getChild("event", NS_QUEUES);
    if (event) {
        var operation = event.getAttribute("operation");
        for (var i = 0; i < this._messageHandlers.length; i++) {
            if (this._messageHandlers[i].call(this, event, operation)) {
                return true;
            }
        }
    }

    return false;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageQueueAdd = function (event, operation) {
    if (operation != 'add') {
        return false;
    }

    var els = event.getElementsByTagName("queue");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var id = el.getAttribute("id");
        var name = el.getAttribute("name");
        var queue = this.getQueue(id);

        if (queue === null) {
            queue = new Queue(id, name);

            this._queues.push(queue);
            this._fire("queue_added", queue);
        }
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageQueueRemove = function (event, operation) {
    if (operation != 'remove') {
        return false;
    }

    var els = event.getElementsByTagName("queue");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var id = el.getAttribute("id");
        var queue = this.getQueue(id);

        if (queue) {
            for (var q in this._queues) {
                if (this._queues[q] == queue) {
                    this._queues.splice(q, 1);
                    this._fire("queue_removed", queue);
                    break;
                }
            }
        }
    }

    return true;
}


/**
 * @private
 */
QueuesPlugin.prototype._handleMessageMemberAdd = function (event, operation) {
    if (operation != 'add') {
        return false;
    }

    var els = event.getElementsByTagName("member");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var options = this._parseMemberItem(el);
        var queue = this.getQueue(options['queue']);
        if (!queue) {
            continue;
        }

        var member = queue.getMember(options['location']);
        if (member) {
            continue;
        }

        member = QueueMember.fromObject(options);
        queue._addMember(member);

        this._fire("member_added", queue, member);
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageMemberUpdate = function (event, operation) {
    if (operation != 'update') {
        return false;
    }

    var els = event.getElementsByTagName("member");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var options = this._parseMemberItem(el);
        var queue = this.getQueue(options['queue']);
        if (!queue) {
            continue;
        }

        var member = queue.getMember(options['location']);
        if (!member) {
            continue;
        }

        member._updateFromObject(options);
        this._fire("member_updated", queue, member);
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageMemberRemove = function (event, operation) {
    if (operation != 'remove') {
        return false;
    }

    var els = event.getElementsByTagName("member");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var options = this._parseMemberItem(el);
        var queue = this.getQueue(options['queue']);
        if (!queue) {
            continue;
        }

        var member = queue.getMember(options['location']);
        if (!member) {
            continue;
        }

        queue._removeMember(member);
        this._fire("member_removed", queue, member);
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageMemberCallAdd = function (event, operation) {
    if (operation != 'add') {
        return false;
    }

    var els = event.getElementsByTagName("call");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var options = this._parseMemberCallItem(el);
        var queue = this.getQueue(options['queue']);
        if (!queue) {
            continue;
        }

        var member = queue.getMember(options['location']);
        if (!member) {
            continue;
        }

        var call = QueueCall.fromObject(options);
        member._addCall(call);

        this._fire("call_added", queue, member, call);
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageMemberCallRemove = function (event, operation) {
    if (operation != 'remove') {
        return false;
    }

    var els = event.getElementsByTagName("call");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var options = this._parseMemberCallItem(el);
        var queue = this.getQueue(options['queue']);
        if (!queue) {
            continue;
        }

        var member = queue.getMember(options['location']);
        if (!member) {
            continue;
        }


        var call = member.getCall(options['channel']);
        if (!call) {
            continue;
        }

        member._removeCall(call);
        this._fire("call_removed", queue, member, call);
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageUserJoin = function (event, operation) {
    if (operation != 'join') {
        return false;
    }

    var els = event.getElementsByTagName("user");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var options = this._parseUserItem(el);
        var queue = this.getQueue(options['queue']);
        if (!queue) {
            continue;
        }

        var user = queue.getMember(options['channel']);
        if (user) {
            continue;
        }

        user = QueueUser.fromObject(options);
        queue._addUser(user);

        this._fire("user_join", queue, user);
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleMessageUserLeave = function (event, operation) {
    if (operation != 'leave') {
        return false;
    }

    var els = event.getElementsByTagName("user");
    if (els.length == 0) {
        return false;
    }

    for (var i = 0; i < els.length; i++) {
        var el = els.item(i);
        var options = this._parseUserItem(el);
        var queue = this.getQueue(options['queue']);
        if (!queue) {
            continue;
        }

        var user = queue.getUser(options['channel']);
        if (!user) {
            continue;
        }

        queue._removeUser(user);
        this._fire("user_left", queue, user);
    }

    return true;
}

/**
 * @private
 */
QueuesPlugin.prototype._handleSubscribeResponse = function (iq, callback, scope) {
    this._queues = this._parseSubscribeResponse(iq);

    for (var i = 0; i < this._queues.length; i++) {
        this._fire("queue_added", this._queues[i]);
    }

    if (typeof (callback) == 'function') {
        callback.call(scope, this._queues);
    }
}

/**
 * @private
 */
QueuesPlugin.prototype._handleUnsubscribeResponse = function (iq, callback, scope) {
    for (var i = 0; i < this._queues.length; i++) {
        this._fire("queue_removed", this._queues[i]);
    }

    this._queues = [];
    this._subscribed = false;

    if (typeof (callback) == 'function') {
        callback.call(scope);
    }
}

/**
 * @private
 */
QueuesPlugin.prototype._createIqHandler = function (callback, scope) {
    return {
        error_handler: function (iq) {
            var node = iq.getNode();
            var errors = node.getElementsByTagName("error");
            var reason = "unknown";

            if (errors.length > 0) {
                var error = errors[0];
                var type = error.firstChild;
                if (type) {
                    reason = type.tagName;
                }
            }

            callback.call(scope, reason);
        },
        result_handler: function () {
            callback.call(scope, null);
        }
    }
}

// ============================================================
// Private functions
// ============================================================

/**
 * @private
 */
QueuesPlugin.prototype._createSubscribePacket = function () {
    var packet = new JSJaCIQ().setType('set');
    var query = packet.setQuery(NS_QUEUES);
    var subscribe = packet.getDoc().createElement('subscribe');
    query.appendChild(subscribe);

    return packet;
};

/**
 * @private
 */
QueuesPlugin.prototype._createUnsubscribePacket = function () {
    var packet = new JSJaCIQ().setType('set');
    var query = packet.setQuery(NS_QUEUES);
    var unsubscribe = packet.getDoc().createElement('unsubscribe');
    query.appendChild(unsubscribe);

    return packet;
};

/**
 * @private
 */
QueuesPlugin.prototype._createAddPacket = function (queue, extension) {
    var packet = new JSJaCIQ().setType('set');
    var query = packet.setQuery(NS_QUEUES);
    var add = packet.getDoc().createElement('add');
    add.setAttribute('queue', queue.getId());
    add.setAttribute('extension', extension);
    query.appendChild(add);

    return packet;
};

/**
 * @private
 */
QueuesPlugin.prototype._createRemovePacket = function (queue, member) {
    var packet = new JSJaCIQ().setType('set');
    var query = packet.setQuery(NS_QUEUES);
    var remove = packet.getDoc().createElement('remove');
    remove.setAttribute('queue', queue.getId());
    remove.setAttribute('location', member.getLocation());
    query.appendChild(remove);

    return packet;
};

/**
 * @private
 */
QueuesPlugin.prototype._createPausePacket = function (queue, member) {
    var packet = new JSJaCIQ().setType('set');
    var query = packet.setQuery(NS_QUEUES);
    var pause = packet.getDoc().createElement('pause');
    pause.setAttribute('queue', queue.getId());
    pause.setAttribute('location', member.getLocation());
    query.appendChild(pause);

    return packet;
};

/**
 * @private
 */
QueuesPlugin.prototype._createResumePacket = function (queue, member) {
    var packet = new JSJaCIQ().setType('set');
    var query = packet.setQuery(NS_QUEUES);
    var pause = packet.getDoc().createElement('unpause');
    pause.setAttribute('queue', queue.getId());
    pause.setAttribute('location', member.getLocation());
    query.appendChild(pause);

    return packet;
};


/**
 *
 * @param event
 * @returns {Array}
 * @private
 */
QueuesPlugin.prototype._parseSubscribeResponse = function (iq) {
    var root = iq.getChild("queues", NS_QUEUES);
    var queueEls = root.getElementsByTagName("queue");
    var queues = [];

    for (var i = 0; i < queueEls.length; i++) {
        var queueEl = queueEls.item(i);
        var queueId = queueEl.getAttribute("id");
        var queueName = queueEl.getAttribute("name");
        var queue = new Queue(queueId, queueName);
        var memberEls = queueEl.getElementsByTagName("member");
        var userEls = queueEl.getElementsByTagName("user");

        for (var c = 0; c < memberEls.length; c++) {
            var memberEl = memberEls.item(c);
            var member = QueueMember.fromObject(this._parseMemberItem(memberEl));

            var callEls = memberEl.getElementsByTagName("call");
            for (var s = 0; s < callEls.length; s++) {
                var call = QueueCall.fromObject(this._parseMemberCallItem(callEls[s]));

                member._addCall(call);
            }

            queue._addMember(member);
        }

        for (var c = 0; c < userEls.length; c++) {
            var userEl = userEls.item(c);
            var user = QueueUser.fromObject(this._parseUserItem(userEl));
            queue._addUser(user);
        }

        queues.push(queue);
    }

    return queues;
};

/**
 * @param {DOMElement} element
 * @returns {{queue: *, location: *, extension: *, membership: *, penalty: *, status: *, pause: *}}
 * @private
 */
QueuesPlugin.prototype._parseMemberItem = function (element) {
    return {
        queue: element.getAttribute('queue'),
        location: element.getAttribute('location'),
        extension: element.getAttribute('extension'),
        name: element.getAttribute('name'),
        membership: element.getAttribute('membership'),
        penalty: element.getAttribute('penalty'),
        status: element.getAttribute('status'),
        pause: element.getAttribute('pause'),
        sleep: element.getAttribute('sleep')
    }
};

/**
 * @param {DOMElement} element
 * @returns {{queue: *, location: *, channel: *, destination: *, calleeNumber: *, calleeName: *, duration: *}}
 * @private
 */
QueuesPlugin.prototype._parseMemberCallItem = function (element) {
    return {
        queue: element.getAttribute('queue'),
        location: element.getAttribute('location'),
        channel: element.getAttribute('channel'),
        destination: element.getAttribute('destination'),
        calleeNumber: element.getAttribute('connected_line_num'),
        calleeName: element.getAttribute('connected_line_name'),
        duration: element.getAttribute('duration')
    }
};

/**
 * @param {DOMElement} element
 * @returns {{queue: *, channel: *, num: *, name: *, duration: *}}
 * @private
 */
QueuesPlugin.prototype._parseUserItem = function (element) {
    return {
        queue: element.getAttribute('queue'),
        channel: element.getAttribute('channel'),
        num: element.getAttribute('num'),
        name: element.getAttribute('name'),
        duration: element.getAttribute('duration')
    }
};

// ============================================================
// Extra classes
// ============================================================

/**
 * @memberof WTAPI.QueuesPlugin
 * @alias WTAPI.QueuesPlugin.Queue
 * @public
 * @constructor
 */
function Queue(id, name) {
    this._members = [];
    this._users = [];

    /**
     * Returns unique id of current Queue
     *
     * @public
     * @returns {string}
     */
    this.getId = function () {
        return id;
    }

    /**
     * Returns name of current Queue
     *
     * @public
     * @returns {string}
     */
    this.getName = function () {
        return name;
    }
}

/**
 * Gets a queue unique identity
 *
 * @returns {String}
 */
Queue.prototype.getId = function () {
    return this._id;
}

/**
 * Gets a member by location
 *
 * @param location
 * @returns {QueueMember}
 */
Queue.prototype.getMember = function (location) {
    for (var i = 0; i < this._members.length; i++) {
        if (this._members[i].getLocation() == location) {
            return this._members[i];
        }
    }

    return null;
}

/**
 * Gets a list of members (agents) that are in queue
 *
 * @returns {Array}
 */
Queue.prototype.getMembers = function () {
    return this._members;
}

/**
 * @private
 */
Queue.prototype._addMember = function (member) {
    this._members.push(member);
}

/**
 * @private
 */
Queue.prototype._removeMember = function (member) {
    for (var i in this._members) {
        if (this._members[i] == member) {
            this._members.splice(i, 1);
            break;
        }
    }
}

/**
 * Gets User using his channel identity
 *
 * @param channel
 * @returns {QueueUser}
 */
Queue.prototype.getUser = function (channel) {
    for (var i = 0; i < this._users.length; i++) {
        if (this._users[i].getChannel() == channel) {
            return this._users[i];
        }
    }

    return null;
}

/**
 * Gets users that a calling to queue
 *
 * @returns {Array}
 */
Queue.prototype.getUsers = function () {
    return this._users;
}

/**
 * @private
 */
Queue.prototype._addUser = function (user) {
    this._users.push(user);
}

/**
 * @private
 */
Queue.prototype._removeUser = function (user) {
    for (var i in this._users) {
        if (this._users[i] == user) {
            this._users.splice(i, 1);
            break;
        }
    }
}

/**
 * @memberof WTAPI.QueuesPlugin
 * @alias WTAPI.QueuesPlugin.QueueMember
 * @public
 * @constructor
 */
function QueueMember(location, extension, name, membership, penalty, status, pause, sleep) {
    this._location = location;
    this._extension = extension;
    this._name = name;
    this._membership = membership;
    this._penalty = penalty;
    this._status = status;
    this._pause = pause;
    this._sleep = parseInt(sleep);
    this._sleepSetTime = Math.round(new Date().getTime() / 1000);
    this._calls = [];
}

/**
 * @private
 * @returns {QueueMember}
 */
QueueMember.fromObject = function (o) {
    return new QueueMember(o.location, o.extension, o.name, o.membership, o.penalty, o.status, o.pause, o.sleep);
}

/**
 * Gets a unique identifier of a Member that are on Queue
 *
 * @returns {String}
 */
QueueMember.prototype.getLocation = function () {
    return this._location;
}

/**
 * Gets an extension of Member (e.g. 100, 200, etc...)
 *
 * @returns {String}
 */
QueueMember.prototype.getExtension = function () {
    return this._extension;
}

/**
 * Gets a Member name
 *
 * @returns {String}
 */
QueueMember.prototype.getName = function () {
    return this._name;
}

/**
 * Checks whether Member is statically added to Queue (e.g. can't be removed by this API)
 *
 * @returns {boolean}
 */
QueueMember.prototype.isStaticMember = function () {
    return (this._membership == 'static');
}

/**
 * Checks whether Member is dynamically added to Queue
 *
 * @returns {boolean}
 */
QueueMember.prototype.isDynamicMember = function () {
    return (this._membership == 'dynamic');
}

/**
 * Gets a Member penalty in Queue.
 * If the strategy of Queue is defined as 'ringall', then only those available
 * members with the lowest priorities will ring.
 *
 * @returns {string}
 */
QueueMember.prototype.getPenalty = function () {
    return this._penalty;
}

/**
 * Gets a Member status in Queue
 * Possible statuses are: not_inuse, inuse, busy, invalid, unavailable, ringing, ringinuse, onhold, unknown
 *
 * @returns {String}
 */
QueueMember.prototype.getStatus = function () {
    return this._status;
}

/**
 * Checks whether Member is paused in that Queue
 *
 * @returns {boolean}
 */
QueueMember.prototype.isPaused = function () {
    return (this._pause == "true");
}


/**
 * Gets a sleep time in seconds (e.g. time from a last call)
 * @returns {number}
 */
QueueMember.prototype.getSleepTime = function () {
    var time = Math.round(new Date().getTime() / 1000);
    var offset = time - this._sleepSetTime;
    return this._sleep + offset;
}

/**
 * Gets a Talk time in seconds
 *
 * @returns {integer}
 */
QueueMember.prototype.getTalkTime = function () {
    if (this._calls.length > 0) {
        var call = this._calls[0];
        return call.getDuration();
    }

    return 0;
}

/**
 * Gets an member active call by channel
 *
 * @param {String} channel
 * @returns {QueueCall|null}
 */
QueueMember.prototype.getCall = function (channel) {
    for (var i = 0; i < this._calls.length; i++) {
        if (this._calls[i].getChannel() == channel) {
            return this._calls[i];
        }
    }

    return null;
}

/**
 * Gets an array of active calls of that member in queue
 *
 * @returns {Array}
 */
QueueMember.prototype.getCalls = function () {
    return this._calls;
}

/**
 * @private
 */
QueueMember.prototype._addCall = function (call) {
    this._calls.push(call);
}

/**
 * @private
 */
QueueMember.prototype._removeCall = function (call) {
    for (var i in this._calls) {
        if (this._calls[i] == call) {
            this._calls.splice(i, 1);
            break;
        }
    }

    if (this._calls.length == 0) {
        this._sleepSetTime = Math.round(new Date().getTime() / 1000);
    }
}

/**
 * @param {Object} o
 * @private
 */
QueueMember.prototype._updateFromObject = function (o) {
    this._location = o.location;
    this._extension = o.extension;
    this._membership = o.membership;
    this._penalty = o.penalty;
    this._status = o.status;
    this._pause = o.pause;
    this._sleep = parseInt(o.sleep);
    this._sleepSetTime = Math.round(new Date().getTime() / 1000);
}

/**
 * @memberof WTAPI.QueuesPlugin
 * @alias WTAPI.QueuesPlugin.QueueUser
 * @public
 * @constructor
 */
function QueueUser(channel, num, name, duration) {
    this._channel = channel;
    this._num = num;
    this._name = name;
    this._duration = parseInt(duration);
    this._durationSetTime = Math.round(new Date().getTime() / 1000);
}

QueueUser.fromObject = function (o) {
    return new QueueUser(o.channel, o.num, o.name, o.duration);
}

/**
 * Gets a unique identifier of a User that are on Queue
 *
 * @returns {String}
 */
QueueUser.prototype.getChannel = function () {
    return this._channel;
}

/**
 * Gets a User number that are calling to Queue
 *
 * @returns {String}
 */
QueueUser.prototype.getNumber = function () {
    return this._num;
}

/**
 * Gets a User name that are calling to Queue
 *
 * @returns {String}
 */
QueueUser.prototype.getName = function () {
    return this._name;
}

/**
 * Gets a waiting for answer time in seconds.
 *
 * @returns {number}
 */
QueueUser.prototype.getDuration = function () {
    var time = Math.round(new Date().getTime() / 1000);
    var offset = time - this._durationSetTime;
    return this._duration + offset;
}

/**
 * @memberof WTAPI.QueuesPlugin
 * @alias WTAPI.QueuesPlugin.QueueCall
 * @public
 * @constructor
 */
function QueueCall(channel, destination, calleeNumber, calleeName, duration) {
    this._channel = channel;
    this._destinationChannel = destination;
    this._calleeNumber = calleeNumber;
    this._calleeName = calleeName;
    this._duration = parseInt(duration);
    this._durationSetTime = Math.round(new Date().getTime() / 1000);
}

/**
 * @private
 * @returns {QueueCall}
 */
QueueCall.fromObject = function (o) {
    return new QueueCall(o.channel, o.destination, o.calleeNumber, o.calleeName, o.duration);
}

/**
 * Gets a call channel identity
 *
 * @returns {*}
 */
QueueCall.prototype.getChannel = function () {
    return this._channel;
}

/**
 * @private
 * @returns {String}
 */
QueueCall.prototype.getDestinationChannel = function () {
    return this._destinationChannel;
}

/**
 * Gets a callee number
 *
 * @returns {String}
 */
QueueCall.prototype.getCalleeNumber = function () {
    return this._calleeNumber;
}

/**
 * Gets a callee name
 *
 * @returns {String}
 */
QueueCall.prototype.getCalleeName = function () {
    return this._calleeName;
}

/**
 * Gets a call duration in seconds.
 *
 * @returns {number}
 */
QueueCall.prototype.getDuration = function () {
    var time = Math.round(new Date().getTime() / 1000);
    var offset = time - this._durationSetTime;
    return this._duration + offset;
}

export default QueuesPlugin;