// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var C, Compressed, Generic, KeyMaterial, Literal, MessageParser, OnePassSignature, PKESK, PacketParser, SEIPD, Signature, SlicerBuffer, UserAttribute, UserID, inspect, parse, util, _ref;

  util = require('../util');

  SlicerBuffer = require('./buffer').SlicerBuffer;

  C = require('../const').openpgp;

  KeyMaterial = require('./packet/keymaterial').KeyMaterial;

  Signature = require('./packet/signature').Signature;

  _ref = require('./packet/sess'), SEIPD = _ref.SEIPD, PKESK = _ref.PKESK;

  UserID = require('./packet/userid').UserID;

  UserAttribute = require('./packet/user_attribute').UserAttribute;

  Compressed = require('./packet/compressed').Compressed;

  Generic = require('./packet/generic').Generic;

  OnePassSignature = require('./packet/one_pass_sig').OnePassSignature;

  Literal = require('./packet/literal').Literal;

  inspect = require('util').inspect;

  MessageParser = (function() {
    function MessageParser(slice) {
      this.slice = slice;
    }

    MessageParser.prototype.parse = function() {
      var _results;
      _results = [];
      while (this.slice.rem()) {
        _results.push(this.parse_packet());
      }
      return _results;
    };

    MessageParser.prototype.parse_packet = function() {
      return (new PacketParser(this.slice)).parse();
    };

    return MessageParser;

  })();

  PacketParser = (function() {
    function PacketParser(slice) {
      this.slice = slice;
      this.body = null;
      this.real_packet_len = null;
      this.tag = null;
      this.len = null;
      this.header_len = null;
    }

    PacketParser.prototype.parse_header = function() {
      this.parse_tag_and_len();
      this.header_len || (this.header_len = this.slice.offset());
      this.body || (this.body = new SlicerBuffer(this.slice.read_buffer(this.len)));
      this.real_packet_len || (this.real_packet_len = this.len);
      return this.slice.unclamp();
    };

    PacketParser.prototype.parse = function() {
      var ret;
      this.parse_header();
      ret = this.parse_body();
      return ret;
    };

    PacketParser.prototype.parse_body = function() {
      var packet, pt, raw, sb;
      pt = C.packet_tags;
      sb = this.body;
      raw = sb.peek_rest_to_buffer();
      packet = (function() {
        switch (this.tag) {
          case pt.PKESK:
            return PKESK.parse(sb);
          case pt.one_pass_sig:
            return OnePassSignature.parse(sb);
          case pt.secret_key:
            return KeyMaterial.parse_private_key(sb, {
              subkey: false
            });
          case pt.secret_subkey:
            return KeyMaterial.parse_private_key(sb, {
              subkey: true
            });
          case pt.public_key:
            return KeyMaterial.parse_public_key(sb, {
              subkey: false
            });
          case pt.public_subkey:
            return KeyMaterial.parse_public_key(sb, {
              subkey: true
            });
          case pt.signature:
            return Signature.parse(sb);
          case pt.userid:
            return UserID.parse(sb);
          case pt.user_attribute:
            return UserAttribute.parse(sb);
          case pt.SEIPD:
            return SEIPD.parse(sb);
          case pt.literal:
            return Literal.parse(sb);
          case pt.compressed:
            return Compressed.parse(sb);
          default:
            return new Generic(this.tag, sb);
        }
      }).call(this);
      packet.set({
        tag: this.tag,
        real_packet_len: this.real_packet_len,
        header_len: this.header_len,
        raw: raw
      });
      return packet;
    };

    PacketParser.prototype.parse_tag_and_len = function() {
      var c;
      if (this.slice.len() < 2 || ((c = this.slice.read_uint8()) & 0x80) === 0) {
        throw new Error("This doesn't look like a binary PGP packet (c=" + c + ")");
      }
      if ((c & 0x40) === 0) {
        return this.parse_tag_and_len_old(c);
      } else {
        return this.parse_tag_and_len_new(c);
      }
    };

    PacketParser.prototype.parse_tag_and_len_old = function(c) {
      this.tag = (c & 0x3f) >> 2;
      return this.len = (function() {
        switch (c & 0x03) {
          case 0:
            return this.slice.read_uint8();
          case 1:
            return this.slice.read_uint16();
          case 2:
            return this.slice.read_uint32();
          case 3:
            return this.slice.rem();
        }
      }).call(this);
    };

    PacketParser.prototype.parse_tag_and_len_new = function(c) {
      var ret;
      this.tag = c & 0x3f;
      ret = this.parse_tag_len_new();
      return ret;
    };

    PacketParser.prototype.parse_tag_len_new = function() {
      var c, d, go, lastlen, packet_length, segments;
      go = true;
      segments = [];
      this.len = 0;
      lastlen = 0;
      while (go) {
        go = false;
        c = this.slice.read_uint8();
        lastlen = c < 192 ? c : c === 255 ? this.slice.read_uint32() : c < 224 ? (d = this.slice.read_uint8(), ((c - 192) << 8) + (d + 192)) : (this.header_len || (this.header_len = this.slice.offset()), packet_length = 1 << (c & 0x1f), segments.push(this.slice.read_buffer(packet_length)), go = true, packet_length);
        this.len += lastlen;
      }
      if (segments.length) {
        segments.push(this.slice.read_buffer(lastlen));
        this.body = new SlicerBuffer(Buffer.concat(segments));
        this.len = this.body.length;
        return this.real_packet_len = this.slice.offset();
      }
    };

    return PacketParser;

  })();

  exports.parse = parse = function(buf) {
    return util.katch(function() {
      return (new MessageParser(new SlicerBuffer(buf))).parse();
    });
  };

}).call(this);
