// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var Debugger, F, F2S, Message, SF, dir, flip_dir, log, sflags_to_flags, type;

  log = require("./log");

  F = {
    NONE: 0,
    METHOD: 0x1,
    REMOTE: 0x2,
    SEQID: 0x4,
    TIMESTAMP: 0x8,
    ERR: 0x10,
    ARG: 0x20,
    RES: 0x40,
    TYPE: 0x80,
    DIR: 0x100,
    PORT: 0x200,
    VERBOSE: 0x400,
    ALL: 0xfffffff
  };

  F.LEVEL_0 = F.NONE;

  F.LEVEL_1 = F.METHOD | F.TYPE | F.DIR | F.TYPE;

  F.LEVEL_2 = F.LEVEL_1 | F.SEQID | F.TIMESTAMP | F.REMOTE | F.PORT;

  F.LEVEL_3 = F.LEVEL_2 | F.ERR;

  F.LEVEL_4 = F.LEVEL_3 | F.RES | F.ARG;

  SF = {
    m: F.METHOD,
    a: F.REMOTE,
    s: F.SEQID,
    t: F.TIMESTAMP,
    p: F.ARG,
    r: F.RES,
    e: F.ERR,
    c: F.TYPE,
    d: F.DIRECTION,
    v: F.VERBOSE,
    P: F.PORT,
    A: F.ALL,
    0: F.LEVEL_0,
    1: F.LEVEL_1,
    2: F.LEVEL_2,
    3: F.LEVEL_3,
    4: F.LEVEL_4
  };

  dir = {
    INCOMING: 1,
    OUTGOING: 2
  };

  flip_dir = function(d) {
    if (d === dir.INCOMING) {
      return dir.OUTGOING;
    } else {
      return dir.INCOMING;
    }
  };

  type = {
    SERVER: 1,
    CLIENT_NOTIFY: 2,
    CLIENT_CALL: 3
  };

  F2S = {};

  F2S[F.DIR] = {};

  F2S[F.DIR][dir.INCOMING] = "in";

  F2S[F.DIR][dir.OUTGOING] = "out";

  F2S[F.TYPE] = {};

  F2S[F.TYPE][type.SERVER] = "server";

  F2S[F.TYPE][type.CLIENT_NOTIFY] = "cli.notify";

  F2S[F.TYPE][type.CLIENT_INVOKE] = "cli.invoke";

  exports.constants = {
    type: type,
    dir: dir,
    flags: F,
    sflags: SF,
    field_to_string: F2S
  };

  exports.sflags_to_flags = sflags_to_flags = function(s) {
    var c, i, res, _i, _ref;
    s = "" + s;
    res = 0;
    for (i = _i = 0, _ref = s.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
      c = s.charAt(i);
      res |= SF[c];
    }
    return res;
  };

  exports.Debugger = Debugger = (function() {
    function Debugger(flags, log_obj, log_obj_mthd) {
      this.log_obj = log_obj;
      this.log_obj_mthd = log_obj_mthd;
      this.flags = typeof flags === 'string' ? sflags_to_flags(flags) : flags;
      if (!this.log_obj) {
        this.log_obj = log.new_default_logger();
        this.log_obj_mthd = this.log_obj.info;
      }
    }

    Debugger.prototype.new_message = function(dict) {
      return new Message(dict, this);
    };

    Debugger.prototype._output = function(json_msg) {
      return this.log_obj_mthd.call(this.log_obj, JSON.stringify(json_msg));
    };

    Debugger.prototype._skip_flag = function(f) {
      return f & (F.REMOTE | F.PORT);
    };

    Debugger.prototype.call = function(msg) {
      var V, do_copy, f2s, flag, key, new_json_msg, uck, val, _ref;
      new_json_msg = {};
      V = this.flags & F.VERBOSE;
      if (this.flags & F.TIMESTAMP) {
        new_json_msg.timestamp = (new Date()).getTime() / 1000.0;
      }
      _ref = msg.to_json_object();
      for (key in _ref) {
        val = _ref[key];
        uck = key.toUpperCase();
        flag = F[uck];
        do_copy = this._skip_flag(flag) ? false : (this.flags & flag) === 0 ? false : key === "res" ? msg.show_res(V) : key === "arg" ? msg.show_arg(V) : true;
        if (do_copy) {
          if ((f2s = F2S[flag]) != null) {
            val = f2s[val];
          }
          new_json_msg[key] = val;
        }
      }
      return this._output(new_json_msg);
    };

    return Debugger;

  })();

  exports.Message = Message = (function() {
    "A debug message --- a wrapper around a dictionary object, with\na few additional methods.";
    function Message(_msg, _debugger) {
      this._msg = _msg;
      this._debugger = _debugger != null ? _debugger : null;
    }

    Message.prototype.response = function(error, result) {
      this._msg.err = error;
      this._msg.res = result;
      this._msg.dir = flip_dir(this._msg.dir);
      return this;
    };

    Message.prototype.to_json_object = function() {
      return this._msg;
    };

    Message.prototype.call = function() {
      return this._debugger.call(this);
    };

    Message.prototype.set = function(k, v) {
      return this.msg[k] = v;
    };

    Message.prototype.is_server = function() {
      return this._msg.type === type.SERVER;
    };

    Message.prototype.is_client = function() {
      return !this.is_server();
    };

    Message.prototype.is_incoming = function() {
      return this._msg.dir === dir.INCOMING;
    };

    Message.prototype.is_outgoing = function() {
      return !this.is_incoming();
    };

    Message.prototype.show_arg = function(V) {
      return V || (this.is_server() && this.is_incoming()) || (this.is_client() && this.is_outgoing());
    };

    Message.prototype.show_res = function(V) {
      return V || (this.is_server() && this.is_outgoing()) || (this.is_client() && this.is_incoming());
    };

    return Message;

  })();

  exports.make_debugger = function(d, lo) {
    if (d === 0) {
      return null;
    } else {
      return new Debugger(d, lo, lo.debug);
    }
  };

}).call(this);
