/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var Thrift = {

    Type: {
        'STOP' : 0,
        'VOID' : 1,
        'BOOL' : 2,
        'BYTE' : 3,
        'I08' : 3,
        'DOUBLE' : 4,
        'I16' : 6,
        'I32' : 8,
        'I64' : 10,
        'STRING' : 11,
        'UTF7' : 11,
        'STRUCT' : 12,
        'MAP' : 13,
        'SET' : 14,
        'LIST' : 15,
        'UTF8' : 16,
        'UTF16' : 17
    },

    MessageType: {
        'CALL' : 1,
        'REPLY' : 2,
        'EXCEPTION' : 3
    },

    objectLength: function(obj) {
        var length = 0;
        for (k in obj)
            if (obj.hasOwnProperty(k))
              length++;
        return length;
    },

    inherits: function(constructor, superConstructor) {
      //Prototypal Inheritance http://javascript.crockford.com/prototypal.html
      function F() {}
      F.prototype = superConstructor.prototype;
      constructor.prototype = new F();
    }
};


Thrift.TException = {};
Thrift.TException.prototype = {
    initialize: function(message, code) {
            this.message = message;
            this.code = (code == null) ? 0 : code;
    }
};


Thrift.TApplicationExceptionType = {
    'UNKNOWN' : 0,
    'UNKNOWN_METHOD' : 1,
    'INVALID_MESSAGE_TYPE' : 2,
    'WRONG_METHOD_NAME' : 3,
    'BAD_SEQUENCE_ID' : 4,
    'MISSING_RESULT' : 5
};

Thrift.TApplicationException = function(message, code) {
    this.message = message;
    this.code = (code == null) ? 0 : code;
};

Thrift.TApplicationException.prototype = {

    read: function(input) {
        while (1) {
            ret = input.readFieldBegin();

            if (ret.ftype == Thrift.Type.STOP)
                break;

            var fid = ret.fid;

            switch (fid) {
                case 1:
                    if (ret.ftype == Thrift.Type.STRING) {
                        ret = input.readString();
                        this.message = ret.value;
                    } else {
                        ret = input.skip(ret.ftype);
                    }

                    break;
                case 2:
                    if (ret.ftype == Thrift.Type.I32) {
                        ret = input.readI32();
                        this.code = ret.value;
                    } else {
                        ret = input.skip(ret.ftype);
                    }
                    break;

                default:
                    ret = input.skip(ret.ftype);
                    break;
            }

            input.readFieldEnd();
        }

        input.readStructEnd();
    },

    write: function(output) {
        var xfer = 0;

        output.writeStructBegin('TApplicationException');

        if (this.message) {
            output.writeFieldBegin('message', Thrift.Type.STRING, 1);
            output.writeString(this.getMessage());
            output.writeFieldEnd();
        }

        if (this.code) {
            output.writeFieldBegin('type', Thrift.Type.I32, 2);
            output.writeI32(this.code);
            output.writeFieldEnd();
        }

        output.writeFieldStop();
        output.writeStructEnd();
    },

    getCode: function() {
        return this.code;
    },

    getMessage: function() {
        return this.message;
    }
};



/**
 *If you do not specify a url then you must handle ajax on your own.
 *This is how to use js bindings in a async fashion.
 */
Thrift.Transport = function(url) {
    this.url = url;
    this.wpos = 0;
    this.rpos = 0;

    this.send_buf = '';
    this.recv_buf = '';
};

Thrift.Transport.prototype = {

    //Gets the browser specific XmlHttpRequest Object
    getXmlHttpRequestObject: function() {

        try { return new XMLHttpRequest() } catch (e) {}
        try { return new ActiveXObject('Msxml2.XMLHTTP') } catch (e) {}
        try { return new ActiveXObject('Microsoft.XMLHTTP') } catch (e) {}

        throw "Your browser doesn't support the XmlHttpRequest object.";

    },

    flush: function() {

        //async mode
        if (this.url == undefined || this.url == '')
            return this.send_buf;

        var xreq = this.getXmlHttpRequestObject();

        if (xreq.overrideMimeType)
            xreq.overrideMimeType('application/json');

        xreq.open('POST', this.url, false);
        xreq.send(this.send_buf);

        if (xreq.readyState != 4)
            throw 'encountered an unknown ajax ready state: ' + xreq.readyState;

        if (xreq.status != 200)
            throw 'encountered a unknown request status: ' + xreq.status;

        this.recv_buf = xreq.responseText;
        this.recv_buf_sz = this.recv_buf.length;
        this.wpos = this.recv_buf.length;
        this.rpos = 0;
    },

    setRecvBuffer: function(buf) {
        this.recv_buf = buf;
        this.recv_buf_sz = this.recv_buf.length;
        this.wpos = this.recv_buf.length;
        this.rpos = 0;
    },

    isOpen: function() {
        return true;
    },

    open: function() {},

    close: function() {},

    read: function(len) {
        var avail = this.wpos - this.rpos;

        if (avail == 0)
            return '';

        var give = len;

        if (avail < len)
            give = avail;

        var ret = this.read_buf.substr(this.rpos, give);
        this.rpos += give;

        //clear buf when complete?
        return ret;
    },

    readAll: function() {
       return this.recv_buf;
    },

    write: function(buf) {
        this.send_buf = buf;
    },

    getSendBuffer: function() {
        return this.send_buf;
    }

};



Thrift.Protocol = function(transport) {
    this.transport = transport;
};

Thrift.Protocol.Type = {};
Thrift.Protocol.Type[Thrift.Type.BOOL] = '"tf"';
Thrift.Protocol.Type[Thrift.Type.BYTE] = '"i8"';
Thrift.Protocol.Type[Thrift.Type.I16] = '"i16"';
Thrift.Protocol.Type[Thrift.Type.I32] = '"i32"';
Thrift.Protocol.Type[Thrift.Type.I64] = '"i64"';
Thrift.Protocol.Type[Thrift.Type.DOUBLE] = '"dbl"';
Thrift.Protocol.Type[Thrift.Type.STRUCT] = '"rec"';
Thrift.Protocol.Type[Thrift.Type.STRING] = '"str"';
Thrift.Protocol.Type[Thrift.Type.MAP] = '"map"';
Thrift.Protocol.Type[Thrift.Type.LIST] = '"lst"';
Thrift.Protocol.Type[Thrift.Type.SET] = '"set"';


Thrift.Protocol.RType = {};
Thrift.Protocol.RType['tf'] = Thrift.Type.BOOL;
Thrift.Protocol.RType['i8'] = Thrift.Type.BYTE;
Thrift.Protocol.RType['i16'] = Thrift.Type.I16;
Thrift.Protocol.RType['i32'] = Thrift.Type.I32;
Thrift.Protocol.RType['i64'] = Thrift.Type.I64;
Thrift.Protocol.RType['dbl'] = Thrift.Type.DOUBLE;
Thrift.Protocol.RType['rec'] = Thrift.Type.STRUCT;
Thrift.Protocol.RType['str'] = Thrift.Type.STRING;
Thrift.Protocol.RType['map'] = Thrift.Type.MAP;
Thrift.Protocol.RType['lst'] = Thrift.Type.LIST;
Thrift.Protocol.RType['set'] = Thrift.Type.SET;

Thrift.Protocol.Version = 1;

Thrift.Protocol.prototype = {

    getTransport: function() {
        return this.transport;
    },

    //Write functions
    writeMessageBegin: function(name, messageType, seqid) {
        this.tstack = new Array();
        this.tpos = new Array();

        this.tstack.push([Thrift.Protocol.Version, '"' +
            name + '"', messageType, seqid]);
    },

    writeMessageEnd: function() {
        var obj = this.tstack.pop();

        this.wobj = this.tstack.pop();
        this.wobj.push(obj);

        this.wbuf = '[' + this.wobj.join(',') + ']';

        this.transport.write(this.wbuf);
     },


    writeStructBegin: function(name) {
        this.tpos.push(this.tstack.length);
        this.tstack.push({});
    },

    writeStructEnd: function() {

        var p = this.tpos.pop();
        var struct = this.tstack[p];
        var str = '{';
        var first = true;
        for (var key in struct) {
            if (first)
                first = false;
            else
                str += ',';

            str += key + ':' + struct[key];
        }

        str += '}';
        this.tstack[p] = str;
    },

    writeFieldBegin: function(name, fieldType, fieldId) {
        this.tpos.push(this.tstack.length);
        this.tstack.push({ 'fieldId': '"' +
            fieldId + '"', 'fieldType': Thrift.Protocol.Type[fieldType]
        });

    },

    writeFieldEnd: function() {
        var value = this.tstack.pop();
        var fieldInfo = this.tstack.pop();

        this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' +
            fieldInfo.fieldType + ':' + value + '}';
        this.tpos.pop();
    },

    writeFieldStop: function() {
        //na
    },

    writeMapBegin: function(keyType, valType, size) {
        //size is invalid, we'll set it on end.
        this.tpos.push(this.tstack.length);
        this.tstack.push([Thrift.Protocol.Type[keyType],
            Thrift.Protocol.Type[valType], 0]);
    },

    writeMapEnd: function() {
        var p = this.tpos.pop();

        if (p == this.tstack.length)
            return;

        if ((this.tstack.length - p - 1) % 2 != 0)
            this.tstack.push('');

        var size = (this.tstack.length - p - 1) / 2;

        this.tstack[p][this.tstack[p].length - 1] = size;

        var map = '}';
        var first = true;
        while (this.tstack.length > p + 1) {
            var v = this.tstack.pop();
            var k = this.tstack.pop();
            if (first) {
                first = false;
            }else {
                map = ',' + map;
            }

            map = '"' + k + '":' + v + map;
        }
        map = '{' + map;

        this.tstack[p].push(map);
        this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
    },

    writeListBegin: function(elemType, size) {
        this.tpos.push(this.tstack.length);
        this.tstack.push([Thrift.Protocol.Type[elemType], size]);
    },

    writeListEnd: function() {
        var p = this.tpos.pop();

        while (this.tstack.length > p + 1) {
            var tmpVal = this.tstack[p + 1];
            this.tstack.splice(p + 1, 1);
            this.tstack[p].push(tmpVal);
        }

        this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
    },

    writeSetBegin: function(elemType, size) {
        this.tpos.push(this.tstack.length);
        this.tstack.push([Thrift.Protocol.Type[elemType], size]);
    },

    writeSetEnd: function() {
        var p = this.tpos.pop();

        while (this.tstack.length > p + 1) {
            var tmpVal = this.tstack[p + 1];
            this.tstack.splice(p + 1, 1);
            this.tstack[p].push(tmpVal);
        }

        this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
    },

    writeBool: function(value) {
        this.tstack.push(value ? 1 : 0);
    },

    writeByte: function(i8) {
        this.tstack.push(i8);
    },

    writeI16: function(i16) {
        this.tstack.push(i16);
    },

    writeI32: function(i32) {
        this.tstack.push(i32);
    },

    writeI64: function(i64) {
        this.tstack.push(i64);
    },

    writeDouble: function(dbl) {
        this.tstack.push(dbl);
    },

    writeString: function(str) {
        // We do not encode uri components for wire transfer:
        if (str === null) {
            this.tstack.push(null);
        } else {
            // concat may be slower than building a byte buffer
            var escapedString = '';
            for (var i = 0; i < str.length; i++) {
                var ch = str.charAt(i);      // a single double quote: "
                if (ch === '\"') {
                    escapedString += '\\\"'; // write out as: \"
                } else if (ch === '\\') {    // a single backslash: \
                    escapedString += '\\\\'; // write out as: \\
                /* Currently escaped forward slashes break TJSONProtocol.
                 * As it stands, we can simply pass forward slashes into
                 * our strings across the wire without being escaped.
                 * I think this is the protocol's bug, not thrift.js
                 * } else if(ch === '/') {   // a single forward slash: /
                 *  escapedString += '\\/';  // write out as \/
                 * }
                 */
                } else if (ch === '\b') {    // a single backspace: invisible
                    escapedString += '\\b';  // write out as: \b"
                } else if (ch === '\f') {    // a single formfeed: invisible
                    escapedString += '\\f';  // write out as: \f"
                } else if (ch === '\n') {    // a single newline: invisible
                    escapedString += '\\n';  // write out as: \n"
                } else if (ch === '\r') {    // a single return: invisible
                    escapedString += '\\r';  // write out as: \r"
                } else if (ch === '\t') {    // a single tab: invisible
                    escapedString += '\\t';  // write out as: \t"
                } else {
                    escapedString += ch;     // Else it need not be escaped
                }
            }
            this.tstack.push('"' + escapedString + '"');
        }
    },

    writeBinary: function(str) {
        this.writeString(str);
    },



    // Reading functions
    readMessageBegin: function(name, messageType, seqid) {
        this.rstack = new Array();
        this.rpos = new Array();

        this.robj = eval(this.transport.readAll());

        var r = {};
        var version = this.robj.shift();

        if (version != Thrift.Protocol.Version) {
            throw 'Wrong thrift protocol version: ' + version;
        }

        r['fname'] = this.robj.shift();
        r['mtype'] = this.robj.shift();
        r['rseqid'] = this.robj.shift();


        //get to the main obj
        this.rstack.push(this.robj.shift());

        return r;
    },


    readMessageEnd: function() {
    },

    readStructBegin: function(name) {
        var r = {};
        r['fname'] = '';

        //incase this is an array of structs
        if (this.rstack[this.rstack.length - 1] instanceof Array)
            this.rstack.push(this.rstack[this.rstack.length - 1].shift());

        return r;
    },

    readStructEnd: function() {
        if (this.rstack[this.rstack.length - 2] instanceof Array)
            this.rstack.pop();
    },

    readFieldBegin: function() {
        var r = {};

        var fid = -1;
        var ftype = Thrift.Type.STOP;

        //get a fieldId
        for (var f in (this.rstack[this.rstack.length - 1])) {
            if (f == null) continue;

            fid = parseInt(f);
            this.rpos.push(this.rstack.length);

            var field = this.rstack[this.rstack.length - 1][fid]

            //remove so we don't see it again
            delete this.rstack[this.rstack.length - 1][fid];

            this.rstack.push(field);

            break;
        }

        if (fid != -1) {

            //should only be 1 of these but this is the only
            //way to match a key
            for (var f in (this.rstack[this.rstack.length - 1])) {
                if (Thrift.Protocol.RType[f] == null) continue;

                ftype = Thrift.Protocol.RType[f];
                this.rstack[this.rstack.length - 1] =
                    this.rstack[this.rstack.length - 1][f];
            }
        }

        r['fname'] = '';
        r['ftype'] = ftype;
        r['fid'] = fid;


        return r;
    },

    readFieldEnd: function() {
        var pos = this.rpos.pop();

        //get back to the right place in the stack
        while (this.rstack.length > pos)
            this.rstack.pop();

    },

    readMapBegin: function(keyType, valType, size) {

        var map = this.rstack.pop();

        var r = {};
        r['ktype'] = Thrift.Protocol.RType[map.shift()];
        r['vtype'] = Thrift.Protocol.RType[map.shift()];
        r['size'] = map.shift();


        this.rpos.push(this.rstack.length);
        this.rstack.push(map.shift());

        return r;
    },

    readMapEnd: function() {
        this.readFieldEnd();
    },

    readListBegin: function(elemType, size) {

        var list = this.rstack[this.rstack.length - 1];

        var r = {};
        r['etype'] = Thrift.Protocol.RType[list.shift()];
        r['size'] = list.shift();


        this.rpos.push(this.rstack.length);
        this.rstack.push(list);

        return r;
    },

    readListEnd: function() {
        this.readFieldEnd();
    },

    readSetBegin: function(elemType, size) {
        return this.readListBegin(elemType, size);
    },

    readSetEnd: function() {
        return this.readListEnd();
    },

    readBool: function() {
        var r = this.readI32();

        if (r != null && r['value'] == '1') {
            r['value'] = true;
        }else {
            r['value'] = false;
        }

        return r;
    },

    readByte: function() {
        return this.readI32();
    },

    readI16: function() {
        return this.readI32();
    },


    readI32: function(f) {
        if (f == undefined)
            f = this.rstack[this.rstack.length - 1];

        var r = {};

        if (f instanceof Array) {
            if (f.length == 0)
                r['value'] = undefined;
            else
                r['value'] = f.shift();

        }else if (f instanceof Object) {
           for (var i in f) {
                if (i == null) continue;
                this.rstack.push(f[i])
                delete f[i];

                r['value'] = i;
                break;
           }
        } else {
            r['value'] = f;
            this.rstack.pop();
        }

        return r;
    },

    readI64: function() {
        return this.readI32();
    },

    readDouble: function() {
        return this.readI32();
    },

    readString: function() {
        var r = this.readI32();
        return r;
    },

    readBinary: function() {
        return this.readString();
    },


    //Method to arbitrarily skip over data.
    skip: function(type) {
        throw 'skip not supported yet';
    }

};
