<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta content="width=device-width, initial-scale=1.0" name="viewport" />
    <title>JS-Waku Chat</title>
    <link rel="apple-touch-icon" href="./favicon.png" />
    <link rel="manifest" href="./manifest.json" />
    <link rel="icon" href="./favicon.ico" />
  </head>

  <body>
    <div><h1>Waku Node Status</h1></div>
    <div id="status"></div>

    <label for="textInput">Message text</label>
    <input
      disabled
      id="textInput"
      placeholder="Type your message here"
      type="text"
    />
    <button disabled id="sendButton" type="button">
      Send Message using Relay
    </button>

    <div><h1>Messages</h1></div>
    <div id="messages"></div>

    <script type="module">
      /**
       * Demonstrate usage of js-waku in the browser. Use relay, gossip sub protocol to send and receive messages.
       * Recommended payload is protobuf. Using simple utf-8 string for demo purposes only.
       */

      import {
        bytesToUtf8,
        utf8ToBytes,
      } from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js";
      import { createRelayNode } from "https://unpkg.com/@waku/create@0.0.5/bundle/index.js";
      import {
        waitForRemotePeer,
        createDecoder,
        createEncoder,
      } from "https://unpkg.com/@waku/core@0.0.10/bundle/index.js";

      const statusDiv = document.getElementById("status");
      const messagesDiv = document.getElementById("messages");
      const textInput = document.getElementById("textInput");
      const sendButton = document.getElementById("sendButton");

      // Every Waku Message has a content topic that categorizes it.
      // It is always encoded in clear text.
      // Recommendation: `/dapp-name/version/functionality/codec`
      // We recommend to use protobuf as codec (`proto`), this demo uses utf-8
      // for simplicity's sake.
      const contentTopic = "/js-waku-examples/1/chat/utf8";

      // Prepare encoder and decoder, `V0` for clear text messages.

      const encoder = createEncoder(contentTopic);
      const decoder = createDecoder(contentTopic);

      try {
        statusDiv.innerHTML = "<p>Starting</p>";

        // Create and starts a Waku node.
        // `default: true` bootstraps by connecting to pre-defined/hardcoded Waku nodes.
        // We are currently working on migrating this method to DNS Discovery.
        //
        // https://js.waku.org/functions/lib_create_waku.createPrivacyNode.html
        const waku = await createRelayNode({ defaultBootstrap: true });
        await waku.start();

        // Add a hook to process all incoming messages on a specified content topic.
        //
        // https://js.waku.org/classes/index.waku_relay.WakuRelay.html#addObserver
        waku.relay.addObserver(
          decoder,
          (message) => {
            // Checks there is a payload on the message.
            // Waku Message is encoded in protobuf, in proto v3 fields are always optional.
            //
            // https://js.waku.org/interfaces/index.proto_message.WakuMessage-1.html#payload
            if (!message.payload) return;

            // Helper method to decode the payload to utf-8. A production dApp should
            // use `wakuMessage.payload` (Uint8Array) which enables encoding a data
            // structure of their choice.
            //
            // https://js.waku.org/functions/index.utils.bytesToUtf8.html
            const text = bytesToUtf8(message.payload);
            messagesDiv.innerHTML =
              `<p>${text}</p><br />` + messagesDiv.innerHTML;
          },
          [contentTopic]
        );

        statusDiv.innerHTML = "<p>Connecting to a peer</p>";

        // Best effort method that waits for the Waku node to be connected to remote
        // waku nodes (peers) and for appropriate handshakes to be done.
        //
        // https://js.waku.org/functions/lib_wait_for_remote_peer.waitForRemotePeer.html
        await waitForRemotePeer(waku);

        // We are now connected to a remote peer, let's define the `sendMessage`
        // function that sends the text input over Waku Relay, the gossipsub
        // protocol.
        sendButton.onclick = async () => {
          const payload = utf8ToBytes(textInput.value);
          await waku.relay.send(encoder, { payload });
          console.log("Message sent!");

          // Reset the text input.
          textInput.value = null;
        };

        // Ready to send & receive messages, enable text input.
        textInput.disabled = false;
        sendButton.disabled = false;
        statusDiv.innerHTML = "<p>Ready!</p>";
      } catch (e) {
        statusDiv.innerHTML = "Failed to start application";
        console.log(e);
      }
    </script>
  </body>
</html>