// **********************************************************************
//
// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

var Ice = require("../Ice/ModuleRegistry").Ice;
Ice.__M.require(module,
    [
        "../Ice/Class",
        "../Ice/Address",
        "../Ice/HashUtil",
        "../Ice/StringUtil",
        "../Ice/EndpointI",
        "../Ice/LocalException"
    ]);

var Address = Ice.Address;
var HashUtil = Ice.HashUtil;
var StringUtil = Ice.StringUtil;
var Class = Ice.Class;
var EndpointParseException = Ice.EndpointParseException;

var IPEndpointI = Class(Ice.EndpointI, {
    __init__: function(instance, ho, po, sa, conId)
    {
        this._instance = instance;
        this._host = ho === undefined ? null : ho;
        this._port = po === undefined ? null : po;
        this._sourceAddr = sa === undefined ? null : sa;
        this._connectionId = conId === undefined ? "" : conId;
    },
    //
    // Marshal the endpoint
    //
    streamWrite: function(s)
    {
        s.startWriteEncaps();
        this.streamWriteImpl(s);
        s.endWriteEncaps();
    },
    getInfo: function()
    {
        var info = new Ice.IPEndpointInfo();
        this.fillEndpointInfo(info);
        return info;
    },
    //
    // Return the endpoint type
    //
    type: function()
    {
        return this._instance.type();
    },
    //
    // Return the protocol string
    //
    protocol: function()
    {
        return this._instance.protocol();
    },
    //
    // Return true if the endpoint is secure.
    //
    secure: function()
    {
        return this._instance.secure();
    },
    connectionId: function()
    {
        return this._connectionId;
    },
    //
    // Return a new endpoint with a different connection id.
    //
    changeConnectionId: function(connectionId)
    {
        if(connectionId === this._connectionId)
        {
            return this;
        }
        else
        {
            return this.createEndpoint(this._host, this._port, connectionId);
        }
    },
    //
    // Return the endpoint information.
    //
    hashCode: function()
    {
        if(this._hashCode === undefined)
        {
            this._hashCode = this.hashInit(5381);
        }
        return this._hashCode;
    },
    options: function()
    {
        //
        // WARNING: Certain features, such as proxy validation in Glacier2,
        // depend on the format of proxy strings. Changes to toString() and
        // methods called to generate parts of the reference string could break
        // these features. Please review for all features that depend on the
        // format of proxyToString() before changing this and related code.
        //
        var s = "";

        if(this._host !== null && this._host.length > 0)
        {
            s += " -h ";
            var addQuote = this._host.indexOf(':') != -1;
            if(addQuote)
            {
                s += "\"";
            }
            s += this._host;
            if(addQuote)
            {
                s += "\"";
            }
        }

        s += " -p " + this._port;

        if(this._sourceAddr !== null && this._sourceAddr.length > 0)
        {
            s += " --sourceAddr " + this._sourceAddr;
        }
        return s;
    },
    compareTo: function(p)
    {
        if(this === p)
        {
            return 0;
        }

        if(p === null)
        {
            return 1;
        }

        if(!(p instanceof IPEndpointI))
        {
            return this.type() < p.type() ? -1 : 1;
        }

        if(this._port < p._port)
        {
            return -1;
        }
        else if(p._port < this._port)
        {
            return 1;
        }

        if(this._host != p._host)
        {
            return this._host < p._host ? -1 : 1;
        }

        if(this._sourceAddr != p._sourceAddr)
        {
            return this._sourceAddr < p._sourceAddr ? -1 : 1;
        }

        if(this._connectionId != p._connectionId)
        {
            return this._connectionId < p._connectionId ? -1 : 1;
        }

        return 0;
    },
    getAddress: function()
    {
        return new Address(this._host, this._port);
    },
    //
    // Convert the endpoint to its Connector string form
    //
    toConnectorString: function()
    {
        return this._host + ":" + this._port;
    },
    streamWriteImpl: function(s)
    {
        s.writeString(this._host);
        s.writeInt(this._port);
    },
    hashInit: function(h)
    {
        h = HashUtil.addNumber(h, this.type());
        h = HashUtil.addString(h, this._host);
        h = HashUtil.addNumber(h, this._port);
        h = HashUtil.addString(h, this._sourceAddr);
        h = HashUtil.addString(h, this._connectionId);
        return h;
    },
    fillEndpointInfo: function(info)
    {
        var self = this;
        info.type = function() { return self.type(); };
        info.datagram = function() { return self.datagram(); };
        info.secure = function() { return self.secure(); };
        info.host = this._host;
        info.port = this._port;
        info.sourceAddress = this._sourceAddr;
    },
    initWithOptions: function(args, oaEndpoint)
    {
        Ice.EndpointI.prototype.initWithOptions.call(this, args);

        if(this._host === null || this._host.length === 0)
        {
            this._host = this._instance.defaultHost();
        }
        else if(this._host == "*")
        {
            if(oaEndpoint)
            {
                this._host = "";
            }
            else
            {
                throw new EndpointParseException("`-h *' not valid for proxy endpoint `" + this + "'");
            }
        }

        if(this._host === null)
        {
            this._host = "";
        }

        if(this._sourceAddr === null)
        {
            if(!oaEndpoint)
            {
                this._sourceAddr = this._instance.defaultSourceAddress();
            }
        }
        else if(oaEndpoint)
        {
            throw new EndpointParseException("`--sourceAddress not valid for object adapter endpoint `" + this + "'");
        }
    },
    initWithStream: function(s)
    {
        this._host = s.readString();
        this._port = s.readInt();
    },
    checkOption: function(option, argument, str)
    {
        if(option === "-h")
        {
            if(argument === null)
            {
                throw new EndpointParseException("no argument provided for -h option in endpoint " + str);
            }

            this._host = argument;
        }
        else if(option === "-p")
        {
            if(argument === null)
            {
                throw new EndpointParseException("no argument provided for -p option in endpoint " + str);
            }

            try
            {
                this._port = StringUtil.toInt(argument);
            }
            catch(ex)
            {
                throw new EndpointParseException("invalid port value `" + argument + "' in endpoint " + str);
            }

            if(this._port < 0 || this._port > 65535)
            {
                throw new EndpointParseException("port value `" + argument + "' out of range in endpoint " + str);
            }
        }
        else if(option === "--sourceAddress")
        {
            if(argument === null)
            {
                throw new EndpointParseException("no argument provided for --sourceAddress option in endpoint " + str);
            }

            this._sourceAddr = argument;
        }
        else
        {
            return false;
        }
        return true;
    }
});

Ice.IPEndpointI = IPEndpointI;
module.exports.Ice = Ice;

