import { CryptoUtil } from './crypto.js';
import { PostContent } from './post.js';

export class Message {
  constructor(content) {
    this.content = content;
  }

  async sign({ publicKey, privateKey }) {
    this.publicKey = await CryptoUtil.exportKey(publicKey);
    // Call toJSON before signing, to match what we'll later send
    this.signature = await CryptoUtil.sign(this.contentToJSON(), privateKey);
    return this;
  }

  static async verify({ content, publicKey, signature }) {
    return CryptoUtil.verify(content, publicKey, signature);
  }

  contentToJSON() {
    return this.content;
  }

  toJSON() {
    return {
      type: this.type,
      content: this.contentToJSON(),
      publicKey: this.publicKey,
      signature: this.signature,
    };
  }
}

export class PostMessage extends Message {
  type = 'post';

  constructor({ post, stake }) {
    super({
      post: PostContent.fromJSON(post),
      stake,
    });
  }

  contentToJSON() {
    return {
      post: this.content.post.toJSON(),
      stake: this.content.stake,
    };
  }
}

export class PeerMessage extends Message {
  type = 'peer';
}

const messageTypes = new Map([
  ['post', PostMessage],
  ['peer', PeerMessage],
]);

export const messageFromJSON = ({ type, content }) => {
  const MessageType = messageTypes.get(type) || Message;
  // const messageContent = MessageType.contentFromJSON(content);
  return new MessageType(content);
};