const WebSocket = require("ws");
const { Client } = require("node-osc");

const ws = new WebSocket(
  "wss://relaxed-werewolf.reticulum.io/socket/websocket?vsn=2.0.0"
);

const STATE_STARTING = "starting";
const STATE_JOINING = "joining";
const STATE_CONNECTED = "connected";

let state = STATE_STARTING;
let hubId = "qPxWfFA";
let fullHubId = `hub:${hubId}`;
let receiveId = 1;
let sendId = 1;
let botSessionId;
let vapidPublicKey;
let avatarId = "qPxWfFA";
let displayName = "000";
// Members keyed by session ID.
let members = {};
let chatStates = {};

const oscClient = new Client("127.0.0.1", 3333);

let dialogOptions = [
  ["START", /(hello|hi)/, "Welcome to the attic, you are getting close.", "START"],


  ["START", /(shell)/, "One correct!", "SHELL"],
  ["START", /(mirror)/, "One correct!", "MIRROR"],
  ["START", /(computer)/, "One correct!", "COMPUTER"],
 
  ["SHELL", /(shell)/, "You already said that!!", "SHELL"],
  ["SHELL", /(mirror)/, "Two correct!", "SHELL_MIRROR"],
  ["SHELL", /(computer)/, "Two correct!", "SHELL_COMPUTER"],
 
  [ "SHELL_COMPUTER", /(shell|computer)/, "You already said that!", "SHELL_COMPUTER"],
  [ "SHELL_COMPUTER", /(mirror)/, "Ahhhhh...... the number of the portal is... 32!", "WIN"],
  [ "SHELL_MIRROR", /(shell|mirror)/, "You already said that!", "SHELL_MIRROR"],
  [ "SHELL_MIRROR", /(computer)/, "Ahhhhh...... the number of the portal is... 32!", "WIN"],
 
  ["MIRROR", /(mirror)/, "You already said that!!", "MIRROR"],
  ["MIRROR", /(shell)/, "Two correct!", "MIRROR_SHELL"],
  ["MIRROR", /(computer)/, "Two correct!", "MIRROR_COMPUTER"],
 
  [ "MIRROR_COMPUTER", /(mirror|computer)/, "You already said that!", "MIRROR_COMPUTER"],
  [ "MIRROR_COMPUTER", /(shell)/, "Ahhhhh...... the number of the portal is... 32!", "WIN"],
  [ "MIRROR_SHELL", /(shell|mirror)/, "You already said that!", "MIRROR_COMPUTER"],
  [ "MIRROR_SHELL", /(computer)/, "Ahhhhh...... the number of the portal is... 32!", "WIN"],
 
  ["COMPUTER", /(comptuer)/, "You already said that!!", "COMPUTER"],
  ["COMPUTER", /(mirror)/, "Two correct!", "COMPUTER_MIRROR"],
  ["COMPUTER", /(shell)/, "Two correct!", "COMPUTER_SHELL"],
 
  [ "COMPUTER_SHELL", /(shell|computer)/, "You already said that!", "COMPUTER_SHELL"],
  [ "COMPUTER_SHELL", /(mirror)/, "Ahhhhh...... the number of the portal is... 32!", "WIN"],
  [ "COMPUTER_MIRROR", /(computer|mirror)/, "You already said that!", "COMPUTER_MIRROR"],
  [ "COMPUTER_MIRROR", /(shell)/, "Ahhhhh...... the number of the portal is... 32!", "WIN"],

  // Guessing game

];

 
   



function sendMessage(roomId, command, body) {
  const message = JSON.stringify([receiveId, sendId, roomId, command, body]);
  ws.send(message);
  sendId++;
}

function receiveMessage(data) {
  const [n1, n2, channel, command, body] = JSON.parse(data);
  if (Number.isInteger(n1)) {
    receiveId = n1;
  }
  if (command === "phx_reply" && state === STATE_STARTING) {
    if (body.status === "ok") {
      console.log("Joining Hubs...");
      state = STATE_JOINING;
      botSessionId = body.response.session_id;
      vapidPublicKey = body.response.vapid_public_key;
      sendMessage(fullHubId, "phx_join", {
        profile: { avatarId, displayName },
        auth_token: null,
        perms_token: null,
        context: { mobile: false, embed: false },
      });
    } else {
      console.log(`ERROR WHILE STARTING: ${JSON.stringify(body)}`);
    }
  } else if (command === "phx_reply" && state == STATE_JOINING) {
    if (body.status === "ok") {
      const hub = body.response.hubs[0];
      console.log(`Connected to ${hub.name}.`);
      state = STATE_CONNECTED;
      setInterval(sendHeartbeat, 30000);
    } else {
      console.log(`ERROR WHILE JOINING: ${JSON.stringify(body)}`);
    }
  } else if (command === "message" && state === STATE_CONNECTED) {
    console.log(body);
    handleChatMessage(body);
  } else if (command === "presence_diff") {
    for (const sessionId of Object.keys(body.joins)) {
      if (sessionId === botSessionId) continue;
      const meta =body.joins[sessionId].metas[0];
      if (meta.presence !== 'room') continue;
      const displayName = meta.profile.displayName;
      const message = `Welcome, dear ${displayName}, to my attic..I like to listen here for any sounds from the outside.. So few come in… Stay here among the paintings for a while, you will see there is no way out..But let’s play a game! In each of these images, there is one element which you must name… For each image, this will be the most central object. But beware! Name all of the elements, and I shall steal your voice. Lo, I shall join the other world. You shall also be set free, for I shall tell you the secret of the portal...`;
      sendMessage(fullHubId, "message", { body: message, type: "chat" });
    }
  } else {
    //console.log(`Unknown command ${command}`);
  }
}

function handleChatMessage(message) {
  if (message.type !== "chat") return;
  // This is the user that sent the message.
  const sessionId = message.session_id;
  // Ignore messages we sent ourselves.
  if (sessionId === botSessionId) return;
  const body = message.body.trim();
  let chatState = chatStates[sessionId] || "START";
  // Find a suitable dialog option.
  for (const [startState, input, output, endState] of dialogOptions) {
    if (startState !== chatState) continue;
    if (body.match(input)) {
      console.log(sessionId, chatState, output);
      setTimeout(() => {
        sendMessage(fullHubId, "message", { body: output, type: "chat" });
        chatState = endState;
        chatStates[sessionId] = chatState;
        if (chatState === 'WIN') {
          oscClient.send("/win");
          chatStates[sessionId] = 'START';
        }
      }, 500 + Math.random() * 1000);
      break;
    }
  }
}

function sendHeartbeat() {
  sendMessage("phoenix", "heartbeat", {});
}

ws.on("open", function () {
  sendMessage("ret", "phx_join", { hub_id: hubId });
});
ws.on("message", receiveMessage);
