var Assertions = require('../common/Assertions.js');
var Types = require('../common/Types.js');
var BinaryData = require('../data/BinaryData.js').BinaryData;
var EventDispatcher = require('../event/EventDispatcher.js').EventDispatcher;
var Headers = require('./Headers.js').Headers;

var Iconv = require('iconv').Iconv;

/**
 * @class Message
 * @requires Class
 *
 * @param {String} url
 */
var Message = function (params) {
    EventDispatcher.call(this);
    this.headers = new Headers();
    this._body = null;
    this._httpVersion = '1.0';
    this._cookieKey = 'message-cookie';
    this._pipelined = false;
};

Message.prototype = Object.create(EventDispatcher.prototype);

Message.prototype.init = function (params) {
    if (params && typeof params == 'object' && params.constructor == Object) {
        var str, methodName, key;
        for (key in params) {
            if (params.hasOwnProperty(key)) {
                methodName = key.charAt(0).toUpperCase() + key.substr(1);
                if (typeof this['set' + methodName] == 'function') {
                    if (typeof this['_set' + methodName] == 'function') {
                        this['_set' + methodName](params[key]);
                    } else {
                        this['set' + methodName](params[key]);
                    }
                }
            }
        }
    }
};

/**
 * sets request headers
 * could be Object with key/value pais or
 * two String Objects first with a header name, second with the header value
 *
 * @param {String} headerName
 * @param {String} headerValue
 * @param {Object} headers
 * @returns {UrlRequest}
 */
Message.prototype.setHeaders = function (headers, normalize) {
    Assertions.isObject(headers, Message.Exception.HEADERS_HAVE_TO_BE_AN_OBJECT);
    this.headers = new Headers(headers, normalize);

    return this;
};

Message.prototype.setHeader = function (name, value, overwrite) {
    this.headers.setHeader(name, value, overwrite);

    return this;
};

Message.prototype.removeHeader = function (name) {
    return this.headers.removeHeader(name);
};

Message.prototype.removeHeaders = function () {
    this.headers.removeHeaders();

    return this;
};

/**
 * returns headers value pair object
 * @returns {Object}
 */
Message.prototype.getHeaders = function () {
    return this.headers.getHeaders();
};

Message.prototype.getHeader = function (name) {
    if (name.toLowerCase() == 'host') {
        var host = this.headers.getHeader(name);
        if (host) {
            return host.toLowerCase();
        } else {
            return host;
        }
    } else {
        return this.headers.getHeader(name);
    }    
}

/**
 * sets the body
 * @param {Object} body
 * @returns {Object}
 */
Message.prototype.setBody = function (body) {
    this._body = body;

    return this;            
};

/**
 * returns body
 * @returns {Object}
 */
Message.prototype.getBody = function () {
    return this._body;
};

Message.prototype.setHttpVersion = function (httpVersion) {
    this._httpVersion = httpVersion;

    return this;
};

Message.prototype.getHttpVersion = function () {
    return this._httpVersion;
};

Message.prototype.setPipelined = function (x) {
    this._pipelined = !!x;
    return this;
};

Message.prototype.isPipelined = function () {
    return this._pipelined;
};

Message.Exception = {};
Message.Exception.WRONG_BUFFER = "Buffer doesn't contain full http response";
Message.Exception.HEADERS_HAVE_TO_BE_AN_OBJECT = "Headers have to be an Object";
Message.Exception.HEADER_NAME_HAS_TO_BE_A_STRING = "Header name has to be a string";

exports.Message = Message;
