const assert = require('assert');
const security = require('../pairing-security');

const alice = security.createIdentity();
const bob = security.createIdentity();
const aliceEphemeral = security.createEphemeralKeyPair();
const bobEphemeral = security.createEphemeralKeyPair();
const aliceMember = {
  hostId: 'alice',
  publicKeyPem: alice.publicKeyPem,
  challenge: 'alice-challenge',
  ephemeralPublicKeyPem: aliceEphemeral.publicKeyPem,
  pairingNonce: 'alice-nonce',
};
const bobMember = {
  hostId: 'bob',
  publicKeyPem: bob.publicKeyPem,
  challenge: 'bob-challenge',
  ephemeralPublicKeyPem: bobEphemeral.publicKeyPem,
  pairingNonce: 'bob-nonce',
};

assert.notStrictEqual(alice.fingerprint, bob.fingerprint);
assert.strictEqual(security.validIdentity(alice), true);
assert.strictEqual(security.validIdentity({
  publicKeyPem: alice.publicKeyPem,
  privateKeyPem: bob.privateKeyPem,
}), false);

const transcriptA = security.pairingTranscript('pairing-1', [aliceMember, bobMember]);
const transcriptB = security.pairingTranscript('pairing-1', [bobMember, aliceMember]);
assert.strictEqual(transcriptA, transcriptB);
assert.match(security.pairingCode(transcriptA), /^\d{6}$/);
assert.strictEqual(security.pairingCode(transcriptA), security.pairingCode(transcriptB));

const signature = security.signTranscript(alice.privateKeyPem, transcriptA);
assert.strictEqual(
  security.verifyTranscript(alice.publicKeyPem, transcriptA, signature),
  true
);
assert.strictEqual(
  security.verifyTranscript(bob.publicKeyPem, transcriptA, signature),
  false
);

const socketTranscript = security.socketTranscript([aliceMember, bobMember]);
const reconnectSignature = security.signTranscript(
  alice.privateKeyPem,
  `${socketTranscript}|connection-enabled:true`
);
assert.strictEqual(
  security.verifyTranscript(
    alice.publicKeyPem,
    `${socketTranscript}|connection-enabled:true`,
    reconnectSignature
  ),
  true
);
assert.strictEqual(
  security.verifyTranscript(
    alice.publicKeyPem,
    `${socketTranscript}|connection-enabled:false`,
    reconnectSignature
  ),
  false
);
const aliceSessionKey = security.deriveSessionKey(
  aliceEphemeral.privateKeyPem,
  bobEphemeral.publicKeyPem,
  socketTranscript
);
const bobSessionKey = security.deriveSessionKey(
  bobEphemeral.privateKeyPem,
  aliceEphemeral.publicKeyPem,
  socketTranscript
);
assert.deepStrictEqual(aliceSessionKey, bobSessionKey);

const wrapper = security.sealFrame(
  aliceSessionKey,
  { type: 'coord', x: 12, y: 34 },
  {
    transport: 'tcp',
    senderHostId: 'alice',
    receiverHostId: 'bob',
  },
  1
);
assert.deepStrictEqual(
  security.openFrame(
    bobSessionKey,
    wrapper,
    {
      transport: 'tcp',
      senderHostId: 'alice',
      receiverHostId: 'bob',
    }
  ),
  { type: 'coord', x: 12, y: 34 }
);

const tampered = Object.assign({}, wrapper, { data: `${wrapper.data.slice(0, -2)}AA` });
assert.throws(() => {
  security.openFrame(
    bobSessionKey,
    tampered,
    {
      transport: 'tcp',
      senderHostId: 'alice',
      receiverHostId: 'bob',
    }
  );
});

const store = {};
assert.strictEqual(security.ensureIdentity(store), true);
assert.strictEqual(security.ensureIdentity(store), false);
assert.match(security.shortFingerprint(store.identity.fingerprint), /^[A-F0-9]{4}( [A-F0-9]{4}){3}$/);

console.log('pairing security tests passed');
