const fs = require('fs');
const path = require('path');
const protobuf = require('protocol-buffers');

// FIXME: to work around the lack of `import` support in the protocol-buffers lib
// (see https://github.com/mafintosh/protocol-buffers/issues/56)
// we're concatenating all of our protos into one big string
// Stop doing this when import works!
function loadProtos() {
  const files = ['dir.proto', 'node.proto', 'stmt.proto', 'manifest.proto'];

  // parsing will fail if there's a `syntax` statement that's not the first line of the file
  // so we remove them from the concatenated monster and add back as the first line
  let joined = 'syntax = "proto3";\n';
  const syntaxStmt = new RegExp('^syntax.*$', 'gm');

  for (const file of files) {
    const content = fs.readFileSync(path.join(__dirname, file), { encoding: 'utf-8' });
    joined += content.replace(syntaxStmt, '') + '\n';
  }

  const pb = protobuf(joined);

  return {
    dir: {
      PeerInfo: pb.PeerInfo,
      PublisherInfo: pb.PublisherInfo,
      RegisterPeer: pb.RegisterPeer,
      LookupPeerRequest: pb.LookupPeerRequest,
      LookupPeerResponse: pb.LookupPeerResponse,
      ListPeersRequest: pb.ListPeersRequest,
      ListPeersResponse: pb.ListPeersResponse
    },
    node: {
      Ping: pb.Ping,
      Pong: pb.Pong,
      NodeInfoRequest: pb.NodeInfoRequest,
      NodeInfo: pb.NodeInfo,
      QueryRequest: pb.QueryRequest,
      QueryResult: pb.QueryResult,
      QueryResultValue: pb.QueryResultValue,
      DataRequest: pb.DataRequest,
      DataResult: pb.DataResult,
      DataObject: pb.DataObject,
      PushRequest: pb.PushRequest,
      PushResponse: pb.PushResponse,
      PushValue: pb.PushValue,
      PushEnd: pb.PushEnd,
      PushAccept: pb.PushAccept,
      PushReject: pb.PushReject,
      StreamError: pb.StreamError,
      StreamEnd: pb.StreamEnd,
      SimpleValue: pb.SimpleValue,
      CompoundValue: pb.CompoundValue,
      KeyValuePair: pb.KeyValuePair
    },
    stmt: {
      SimpleStatement: pb.SimpleStatement,
      CompoundStatement: pb.CompoundStatement,
      EnvelopeStatement: pb.EnvelopeStatement,
      ArchiveStatement: pb.ArchiveStatement,
      StatementBody: pb.StatementBody,
      Statement: pb.Statement
    },
    manifest: {
      Manifest: pb.Manifest,
      ManifestBody: pb.ManifestBody,
      NodeManifest: pb.NodeManifest
    }
  };
}

const { dir, node, stmt } = loadProtos();
module.exports = { dir, node, stmt };