/**
 * Copyright 2016 the WHATAP project authors. All rights reserved.
 * Use of this source code is governed by a license that
 * can be found in the LICENSE file.
 */


var Pack = require('./pack'),
    Long = require('long'),
    StringKeyLinkedMap = require('../util/stringkey-linkedmap'),
    PackEnum = require('./packenum'),
    BooleanValue = require('../value/boolean-value'),
    NumberValue = require('../value/number-value'),
    TextValue = require('../value/text-value'),
    DecimalValue = require('../value/decimal-value'),
    ListValue = require('../value/list-value'),
    MapValue = require('../value/map-value');

function ParamPack() {
    Pack.call(this);

    this.id = 0;
    this.table = new StringKeyLinkedMap();
    this.request = Long.ZERO;
    this.response = Long.ZERO;

    this.size = function () {
        return this.table.size();
    };

    this.isEmpty = function () {
        return this.size() === 0
    };

    this.containsKey = function (key) {
        return this.table.containsKey(key);
    };

    this.keys = function () {
        return this.table.keys();
    };

    this.getValue = function (key) {
        return this.table.get(key);
    };

    this.getBoolean = function (key) {
        var v = this.getValue(key);
        if(v instanceof BooleanValue) {
            return v.value;
        }
        return false;
    };

    this.getInt = function (key) {
        var v = this.getValue(key);
        if(v instanceof NumberValue) {
            return v.intValue();
        }
        return 0;
    };

    this.getLong = function (key) {
        var v = this.getValue(key);
        if(v instanceof NumberValue) {
            return v.longValue();
        }
        return Long.ZERO;
    };
    this.getNumber = function (key) {
        var v = this.getValue(key);
        if(v instanceof NumberValue) {
            return v.numberValue();            
        }
        return 0;
    };
    this.getLong = function (key) {
        var v = this.getValue(key);
        if(v instanceof NumberValue) {
            return v.longValue();
        }
        return 0;
    };


    this.getFloat = function (key) {
        var v = this.getValue(key);
        if(v instanceof NumberValue) {
            return v.floatValue();
        }
        return 0;
    };

    this.getText = function (key) {
        var v = this.getValue(key);
        if(v instanceof TextValue) {
            return v.value;
        }
        return null;
    };

    this.putValue = function (key, value) {
        this.table.put(key, value);
    };

    this.putString = function (key, value) {
        var v = new TextValue(value);
        this.table.put(key, v);
    };

    this.putLong = function (key, value) {
        var v = new DecimalValue(value);
        this.table.put(key, v);
    };

    this.remove = function (key) {
        return this.table.remove(key);
    };

    this.clear = function () {
        this.table.clear();
    };

    this.newList = function (name) {
        var list = new ListValue();
        this.putValue(name, list);
        return list;
    };

    this.hashCode = function () {

    };

    this.equals = function (object) {
        return this === object;
    };

    this.toMapValue = function () {
        var map = new MapValue();        
        var en = this.table.keys();
        while(en.hasMoreElements()){
            var k = en.nextElement();
            var v = this.table.get(k);
            map.putValue(k,v);
        }
        return map;
    };

    this.setMapValue = function (mapValue) {
        if(mapValue == null) {
            return this;
        }
        if((mapValue instanceof MapValue) === false) {
            return this;
        }

        var k,v;
        var en = mapValue.keys();
        while(en.hasMoreElements()){
            k = en.nextElement();
            v = mapValue.get(k);
            this.putValue(k,v);
        }
        return this;
    };

    this.getResponse = function () {
        if(this.request === 0) {
            return this;
        }
        this.response = this.request;
        this.request = 0;
        return this;
    }
}

ParamPack.prototype = new Pack();
ParamPack.prototype.constructor = ParamPack;
ParamPack.prototype.getPackType = function () {
    return PackEnum.PARAMETER;
};
ParamPack.prototype.write = function (dout) {
    Pack.prototype.write.call(this, dout);
    dout.writeInt(this.id);
    dout.writeDecimal(this.request);
    dout.writeDecimal(this.response);
    dout.writeDecimal(this.table.size());

    var key,val;
    var en = this.keys();
    while(en.hasMoreElements()){
        key = en.nextElement();
        val = this.table.get(key);
        dout.writeText(key);
        dout.writeValue(val);
    }
    
};
ParamPack.prototype.read = function (din) {
        Pack.prototype.read.call(this, din);
        this.id = din.readInt();
        this.request = din.readDecLong();
        this.response = din.readDecLong();
        var count = din.readDecNumber();
        var key, val;
        for(var i=0; i<count; i++) {
            key = din.readText();
            val = din.readValue();
            this.putValue(key, val);
        }
    return this;
};

module.exports.ParamPack = ParamPack;