function Dictionary(){
    var getmap;

    (function() {
        var _map = new java.util.HashMap();
        getmap = function(){
            return _map;
        };
    })();

    this.add = function(key, value){
        getmap().put(key, value);
    };
    this.get = function(key){
        return getmap().get(key);
    };
    this.exists = function(key){
	return getmap().keySet().contains(key);
    };
    this.remove = function(key){
	getmap().remove(key);
    };
    this.removeall = function(key){
        getmap().clear();
    };
}

function Option(shortname, longname, argument, description, action){
    this.shortname = shortname;
    this.longname = longname;
    this.argument = argument;
    this.description = description;
    this.action = action;
    this.requires_argument = function(){
        return this.argument != null;
    };
}

function OptionParser(help_message){
    var getshorttooptionmap,
        getlongtooptionmap;

    this.options = [];
    this.help_message = help_message;

    (function() {
        var shorttooptionmap = new Dictionary();
        var longtooptionmap = new Dictionary();

        getshorttooptionmap = function(){
            return shorttooptionmap;
        }

        getlongtooptionmap = function(){
            return longtooptionmap;
        }
    })();

    this.addoption = function(shortname, longname, argument, description, action){
        option = new Option(shortname, longname, argument, description, action);
        getshorttooptionmap().add(shortname, option);
        getlongtooptionmap().add(longname, option);
        this.options.push(option);
    }

    this.addoptionflag = function(shortname, longname, description, action){
        this.addoption(shortname, longname, null, description, action);
    }


    this.parse = function(argv){
        var option;
        for(i = 0; i < argv.length; i++){
            if(argv[i].substr(0,2) == "--"){
                option = getlongtooptionmap().get(argv[i].substr(2));
            }else if(argv[i].substr(0,1) == "-"){
                option = getshorttooptionmap().get(argv[i].substr(1));
            }else{
                throw "Was expecting option. Got " + argv[i];
            }

            if(option == undefined){
                throw "Undefined option: " + argv[i];
            }

            if(option.requires_argument()){
                if(i == argv.length - 1){
                    throw "option " + argv[i] + " requires argument";
                }
                arg = argv[i + 1];
                i++;
                option.action(arg);
            }else{
                option.action();
            }
        }
    }

    this.help = function(){
        ret = "";
        ret = ret + help_message + "\n";
        for(i=0; i< this.options.length; i++){
            ret = ret + "\t-" + this.options[i].shortname + " --" + this.options[i].longname;
            if(this.options[i].argument != null){
                ret = ret + " [" + this.options[i].argument + "]";
            }
            ret = ret + " " + this.options[i].description + "\n";
        }
        return ret;
    }
}

optionparser = new OptionParser("net_tool.js [options]");
var options = {};

optionparser.addoptionflag("c", "connect", 
                           "connect to the host", function(){
    options.connect = true;
});
optionparser.addoptionflag("l", "listen", 
                           "listen for remote host", function(){
    options.connect = false;
});
optionparser.addoption("p", "port", "PORT", 
                       "TCPIP connection port", function(arg){
    options.port = arg;
});
optionparser.addoption("r", "remote-host", 
                       "HOSTNAME", "Hostname to connect to", function(arg){
    options.hostname = arg;
});
optionparser.addoptionflag("h", "help", "print this message", function(){
    print(optionparser.help());
    java.lang.System.exit(0);
});

try{
    optionparser.parse(argv);
}catch(e){
    print(e);
    print("\n");
    print(optionparser.help());
    java.lang.System.exit(1);
}

if(options.connect == undefined){
    print("Must specify connect or listen\n");
    print(optionparser.help());
    java.lang.System.exit(1);
}

if(options.port == undefined){
    print("Must specify a port\n");
    print(optionparser.help());
    java.lang.System.exit(1);
}

if(options.connect && options.hostname == undefined){
    print("In connect mode you must specify a hostname\n");
    print(optionparser.help());
    java.lang.System.exit(1);
}
