/**
 * 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 Long        = require('long'),
    StringKeyLinkedMap = require('../util/stringkey-linkedmap'),
    ValueEnum   = require('./valueenum'),
    Value       = require('./value'),
    BooleanValue = require('./boolean-value'),
    NumberValue  = require('./number-value'),
    FloatValue   = require('./float-value'),
    DoubleValue  = require('./double-value'),
    BooleanValue = require('./boolean-value'),
    TextValue    = require('./text-value'),
    DecimalValue = require('./decimal-value'),
    ListValue    = require('./list-value'),
    IntValue    = require('./int-value');

function MapValue() {
    Value.call(this);

    this.table = new StringKeyLinkedMap();
    this.equals = function(obj) {
        return (this === obj);
    };
}

MapValue.prototype = new Value();
MapValue.prototype.constructor = MapValue;
MapValue.prototype.size = function() {
    return this.table.size();
};
MapValue.prototype.isEmpty = function(){
    return this.table.size() === 0;
};
MapValue.prototype.containsKey = function(key) {
    return this.table.containsKey(key);
};
MapValue.prototype.keys = function() {
    return this.table.keys();
};
MapValue.prototype.get = function(key) {
    return this.table.get(key);
};
MapValue.prototype.getBoolean = function(key) {
    var v = this.get(key);
    if(v instanceof BooleanValue) {
        return v.value;
    }
    return false;
};
MapValue.prototype.getInt = function(key) {
    var v = this.get(key);
    if(v instanceof  NumberValue) {
        return v.intValue();
    }
    return 0;
};
MapValue.prototype.getLong = function(key) {
    var v = this.get(key);
    if(v instanceof NumberValue) {
        return v.longValue();
    }
    return Long.ZERO;
};
MapValue.prototype.getNumber = function(key) {
    var v = this.get(key);
    if(v instanceof NumberValue) {
        return v.numberValue();
    }
    return 0;
};
MapValue.prototype.getFloat = function(key) {
    var v = this.get(key);
    if(v instanceof NumberValue) {
        return v.floatValue();
    }
    return 0;

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

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

MapValue.prototype.putInt = function(key, value) {
    this.table.put(key, new IntValue(value));
    return this;
};
MapValue.prototype.putString = function(key, value) {
    this.table.put(key, new TextValue(value + ""));
    return this;
};
MapValue.prototype.putLong = function(key, value) {
    this.table.put(key, new DecimalValue(value));
    return this;
};
MapValue.prototype.putFloat = function(key, value) {
    this.table.put(key, new FloatValue(value));
    return this;
};
MapValue.prototype.putDouble = function(key, value) {
    this.table.put(key, new DoubleValue(value));
    return this;
};
MapValue.prototype.putBoolean = function(key, value) {
    this.table.put(key, new BooleanValue(value));
    return this;
};

MapValue.prototype.remove = function(key) {
    return this.table.remove(key);
};
MapValue.prototype.clear = function() {
    this.table.clear();
};
MapValue.prototype.toString = function() {
    return this.table.toString();
};
MapValue.prototype.getValueType = function() {
    return ValueEnum.MAP;
};
MapValue.prototype.write = function(dout) {
    dout.writeDecimal(this.table.size());
    var en = this.table.keys();  
    while(en.hasMoreElements()) {
        var key = en.nextElement();
        dout.writeText(key);
        dout.writeValue(this.table.get(key));
    }
};
MapValue.prototype.read = function(din) {
    var count = din.readDecNumber();
    for(var i=0; i<count; i++) {
        var  key = din.readText();
        var value = din.readValue();
        this.putValue(key, value);
    }
    return this;
};
MapValue.prototype.newList = function(name) {
    var list = new ListValue();
    this.putValue(name, list);
    return list;
};
MapValue.prototype.getList = function(key) {
    return this.table.get(key);
};
MapValue.prototype.toObject = function() {
    return this.table;
};
MapValue.prototype.putAllMap = function(m) {
    var en = m.keys();  
    while(en.hasMoreElements()) {
        var key = en.nextElement();
        var value =m.get(key);
        if(value instanceof Value) {
            this.table.put(key,value);
        }
    }
};
MapValue.prototype.putAllMapValue = function(m) {
    this.putAllMap(m);
};
MapValue.prototype.internList = function (key) {
    let lv = this.table.get(key);
    if(!lv){
        lv = new ListValue()
        this.table.put(key, lv);
    }
    return lv;
}

module.exports = MapValue;