var Event = require('../../event/Event').Event;

var RbmqChannel = require('./RbmqChannel').RbmqChannel;
var RbmqOutcomingMessage = require('./RbmqOutcomingMessage').RbmqOutcomingMessage;

var RbmqExchange = function(rbmqConnection, config) {
    RbmqChannel.call(this, rbmqConnection, config);
};

RbmqExchange.prototype = Object.create(RbmqChannel.prototype);

RbmqExchange.prototype.setConfig = function(config) {
    var publishConfig = config.publish || {};
    var newConfig = {
        name: config.name,
        options: {
            durable: config.durable,
            autoDelete: config.autoDelete,
            passive: config.passive,
            type: config.type || 'topic',
            confirm: publishConfig.confirm || false,
            arguments: {}
        },
        bindings: config.bindings || [],
        publish: publishConfig
    };

    if (config.hasOwnProperty('alternateExchange')) {
        newConfig.options.arguments['alternate-exchange'] = config.alternateExchange;
    }

    RbmqChannel.prototype.setConfig.call(this, newConfig);
};

RbmqExchange.prototype.open = function() {
    this._rbmqChannel = this._rbmqConnection._rbmq.exchange(this._config.name, this._config.options);
    RbmqChannel.prototype.open.call(this);
};

RbmqExchange.prototype._onChannelOpened = function() {
    var config = this._config;

    for (var i = 0, l = config.bindings.length; i < l; i++) {
        this._rbmqChannel.bind(config.bindings[i].exchange, config.bindings[i].routingKey);
    }

    RbmqChannel.prototype._onChannelOpened.call(this);
};

RbmqExchange.prototype.publish = function(message) {
    if (!this._opened) {
        message.dispatchEvent(new Event(RbmqOutcomingMessage.Event.REJECTED, {
            message: message,
            error: new Error('Exchange disconnected')
        }));
        return;
    }

    if (message.getRoutingKey() === undefined) {
        message.setRoutingKey(this._config.publish.routingKey || '');
    }

    if (!message.getDeliveryMode()) {
        message.setDeliveryMode(this._config.publish.deliveryMode || RbmqMessage.DMODE_PERSISTENT);
    }

    var options = this._config.options;
    var cb = function(err) {
        if (!err) {
            message.setPublished();
        }

        message.dispatchEvent(new Event(RbmqOutcomingMessage.Event.PUBLISHED, {
            message: message,
            error: err
        }));
    };

    // if not options.confirm node-amqp never call callback :/
    this._rbmqChannel.publish(message.getRoutingKey(), message.getBody(), message.getArguments(), options.confirm ? cb : undefined);

    if (!options.confirm) {
        return cb();
    }
};

RbmqExchange.Event = {};
RbmqExchange.Event.OPENED = RbmqChannel.Event.OPENED;
RbmqExchange.Event.CLOSED = RbmqChannel.Event.CLOSED;

exports.RbmqExchange = RbmqExchange;
