import React, {FC, useEffect, useState} from 'react';
import {produce} from 'immer';
import {subscribe} from '../websocket';

type Client = {
  type: "mobile"|"browser"|"compiler"|"cliui";
  appId?: string;
  ip: string;
  isAlive: boolean;
};

function narrowClient(raw: any): raw is Client {
  try {
    return (["mobile", "browser", "compiler", "cliui"].includes(raw.type)) && 
      (typeof raw.ip === "string") &&
      (typeof raw.isAlive === "boolean");
  } catch (err) {
    console.error("Failed to narrow client", err);
    return false;
  }
}

const SocketClients: FC = function SocketClients() {
  const [clients, setClients] = useState<Client[]>([]);
  useEffect(() => {
    return subscribe('status', (ev: any) => {
      if (ev && Array.isArray(ev.clients)) {
        setClients(
          produce((prevClients) => {
            for (let i = 0; i < ev.clients.length; ++i) {
              const client = ev.clients[i];
              if (narrowClient(client)) {
                const existingIndex = prevClients.findIndex(cl => {
                  return (cl.ip === client.ip) && (cl.type === client.type);
                });
                if (existingIndex >= 0) {
                  prevClients[existingIndex] = client;
                } else {
                  prevClients.push(client);
                }
              }
            }
          })
        ) 
      }
    });
  }, [setClients]);

  const renderedClients = clients.map(it => {
    return (<div
      key={it.ip + '_' + it.type}
      className={it.isAlive ? "border rounded border-green-500" : "border rounded border-red-500"}
    >
      {it.type}
      {it.appId ? <div>{it.appId}</div>:null}
    </div>)
  });

  return (<div>
      Socket clients
      {renderedClients}
    </div>);
}

export default SocketClients;
