import "../../components/theme";
import App from "./App.svelte";
import request from "../../helper/request";

interface IPermission {
   _id: string;
   name: string;
   description: string;
}

let loading = true;
let appName: string;
let permissions: IPermission[] = [];
let accept: () => void;

const app = new App({
   target: document.body,
   props: { loading, accept },
});

const setLoading = (_loading: boolean) => {
   loading = _loading;
   app.$set({ loading });
};

const setAppName = (_appName: string) => {
   appName = _appName;
   app.$set({ appName });
};

const setPermissions = (_permissions: IPermission[]) => {
   permissions = _permissions;
   app.$set({ permissions });
};

const setAccept = (_accept: () => void) => {
   accept = _accept;
   app.$set({ accept });
};

async function getJWT(client_id: string, origin: string) {
   origin = encodeURIComponent(origin);
   client_id = encodeURIComponent(client_id);

   const res = await request(`/api/user/oauth/jwt`, {
      client_id,
      origin,
   });

   return res;
}

async function getRefreshToken(
   client_id: string,
   origin: string,
   permissions: string[]
) {
   origin = encodeURIComponent(origin);
   client_id = encodeURIComponent(client_id);
   const perm = permissions.map((e) => encodeURIComponent(e)).join(",");

   const res = await request(`/api/user/oauth/refresh_token`, {
      client_id,
      origin,
      permissions: perm,
   });

   return res;
}

let started = false;
async function onMessage(msg: MessageEvent<any>) {
   const sendResponse = (data: any) => {
      try {
         console.log("Sending response:", data);
         (msg.source.postMessage as any)(data, msg.origin);
      } catch (err) {
         alert("Something went wrong, please try again later!");
      }
   };
   console.log("Received message", msg, started);
   if (!started) {
      started = true;
      const url = new URL(msg.origin);
      setAppName(url.hostname);

      if (!msg.data.client_id) {
         alert("The site requesting the login is not valid");
         window.close();
         return;
      }

      try {
         if (!msg.data.type || msg.data.type === "jwt") {
            console.log("JWT Request");

            await request(
               "/api/user/oauth/permissions",
               {
                  client_id: msg.data.client_id,
                  origin: url.hostname,
                  permissions: permissions.join(","),
               }
            ); // Will fail if client does not exist

            await new Promise<void>((yes) => {
               console.log("Await user acceptance");
               setLoading(false);
               setAccept(yes);
            });
            console.log("User has accepted");
            const res = await getJWT(msg.data.client_id, url.hostname);
            sendResponse(res);
         } else if (msg.data.type === "refresh") {
            console.log("RefreshToken Request");
            let permissions = msg.data.permissions || [];
            let permissions_resolved = [];

            if (permissions.length > 0) {
               permissions_resolved = await request(
                  "/api/user/oauth/permissions",
                  {
                     client_id: msg.data.client_id,
                     origin: url.hostname,
                     permissions: permissions.join(","),
                  }
               ).then(({ permissions }) => permissions);
            }

            await new Promise<void>((yes) => {
               console.log("Await user acceptance");
               setLoading(false);
               setPermissions(permissions_resolved);
               setAccept(yes);
            });

            console.log("User has accepted");

            const res = await getRefreshToken(
               msg.data.client_id,
               url.hostname,
               permissions
            );
            sendResponse(res);
         }
      } catch (err) {
         sendResponse({ error: true, message: err.message });
      }
      window.close();
   }
}

setTimeout(() => {
   if (!started) {
      console.log("No authentication request received!");
      alert(
         "The site requesting the login does not respond. Please try again later"
      );
   }
}, 10000);

window.addEventListener("message", onMessage);
