<script lang="ts" context="module">
  export enum APPSTATE {
    HOME = "/",
    PROFILE = "/profile",
    HISTORY = "/history",
    HISTORY_ID = "/history_id",
    FRIENDS = "/friends",
    CHANNELS = "/channels",
    LEADERBOARD = "/leaderboard",
    CREATE_GAME = "/create-game",
    MATCHMAKING = "/matchmaking",
    PROFILE_ID = "/profile_id",
  }

</script>

<script lang="ts">
  import { onMount } from "svelte";
  import Navbar from "./components/NavBar.svelte";
  import Modal from "svelte-simple-modal";
  import Profile from "./components/Profile.svelte";
  import MatchHistory from "./components/MatchHistory.svelte";
  import Friends, { addFriend } from "./components/Friends.svelte";
  import Chat from "./components/Chat.svelte";
  import Channels, { formatChannelNames } from "./components/Channels.svelte";
  import Leaderboard from "./components/Leaderboard.svelte";
  import { popup } from "./components/Alert/content";
  import Pong from "./components/Pong/Pong.svelte";
  import type { ChannelsType } from "./components/Channels.svelte";
  import { API_URL } from "./Auth";

  import { store, getUser, login, verify } from "./Auth";
  import FakeLogin from "./FakeLogin.svelte";

  // Single Page Application config
  let appState: string = APPSTATE.HOME;

  async function updateChat() {
    const urlSplit = appState.split("#", 2)
    if (appState.includes(APPSTATE.CHANNELS) && urlSplit.length > 1) {
      const currentChannelName = appState.split("#", 2)[1];
      fetch(API_URL + "/channels", {
        credentials: "include",
        mode: "cors",
      }).then((res) => {
        res.json().then(async (channels) => {
          await formatChannelNames(channels);
          const channel = channels.find((c: ChannelsType) => c.name === currentChannelName);
          if (channel) {
            chan.selectChat(channel.id);
          } else {
            alert("Failed loading channel");
          }
        });
      }).catch(() => {
        alert("Failed loading channel");
      });
    }
  }

  history.replaceState({ appState: "" }, "", "/");
  window.onpopstate = (e: PopStateEvent) => {
    if (e.state) {
      appState = e.state.appState;
      void updateChat();
    }
  };

  function resetAppState() {
    setAppState(APPSTATE.HOME);
  }

  function setAppState(newState: APPSTATE | string) {
  if (newState === appState) return;
    appState = newState;
    history.pushState({ appState }, "", appState);
    void updateChat();
  }

  onMount(() => {
    getUser();
  });
  setInterval(() => {
    getUser();
  }, 15000);

  function clickProfile() {
    profileUsername = $store.username
    setAppState(APPSTATE.PROFILE);
  }

  let profileUsername: string = "";
  async function openIdProfile(event: CustomEvent<string>) {
    profileUsername = event.detail;
    setAppState(APPSTATE.PROFILE_ID);
  }
  $: console.log(profileUsername)

  async function getDMs(username: string): Promise<Response | null> {
	const res = await fetch(API_URL + "/channels/dms/" + username, {
		credentials: "include",
		mode: "cors",
	})
	if (res.ok)
		return res;
	else
		return null;
  }

  let chan: Channels;
  async function openDirectChat(event: CustomEvent<string>) {
    const DMUsername = event.detail;
    let DMChannel: Array<ChannelsType> = [];
    const res = await getDMs(DMUsername)
    if (res && res.ok) {
      DMChannel = await res.json();
      if (DMChannel.length != 0)
        chan.selectChat(DMChannel[0].id);
	  } else {
        console.log("Creating DMChannel: " + $store.username + "&" + DMUsername)
        fetch(API_URL + "/channels", {
          credentials: "include",
          method: "POST",
          mode: "cors",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            name: "none",
            owner: $store.ftId,
            password: "",
            isPrivate: true,
            isDM: true,
            otherDMedUsername: DMUsername
          }),
        }).then(async () => {
          const response = await getDMs(DMUsername)
          if (response && response.ok) {
              DMChannel = await response.json(); 
              if (DMChannel.length != 0) {
                chan.selectChat(DMChannel[0].id);
              } else {
                alert("Error creating DM");
              }
          } else {
            alert("Error creating DM");
          }
        }).catch((error) => {
          alert("Error creating DM");
        })
      }
    }

  async function clickHistory() {
    setAppState(APPSTATE.HISTORY);
  }

  async function clickFriends() {
    setAppState(APPSTATE.FRIENDS);
  }

  async function clickLeaderboard() {
    setAppState(APPSTATE.LEADERBOARD);
  }

  function clickChannels() {
    setAppState(APPSTATE.CHANNELS);
  }
  let selectedChannel: ChannelsType;
  const handleSelectChannel = (channel: ChannelsType) => {
    selectedChannel = channel;
    setAppState(APPSTATE.CHANNELS + "#" + channel.name);
  };

  // GAME
  let pong: Pong;
  let gamePlaying: boolean = false;

  // FAKE LOGIN
  let usernameFake = "test";
  let ftIdFake = "42";
  let fakemenu = true;
  let fakeUser = false;
  function impersonate() {
    const user = {
      username: usernameFake,
      socketKey: ftIdFake,
    };
    store.set(user);
    fakeUser = true;
    fakemenu = false;
  }
</script>

<div>
  <Modal show={$popup}>
  {#if $store === null}
    <div class="login-div">
      <h3 class="test">Please log in with 42 api to access the website.</h3>
      <img
        class="img-42"
        src="https://translate.intra.42.fr/assets/42_logo-7dfc9110a5319a308863b96bda33cea995046d1731cebb735e41b16255106c12.svg"
        alt="logo_42"
      />
      <button class="login-button" type="button" on:click={login}>Log In</button
      >
    </div>
  {:else if $store.twoFA === true && $store.isVerified === false}
    <h1><button type="button" on:click={verify}>verify</button></h1>
  {:else}

    <Navbar
      {clickProfile}
      {clickHistory}
      {clickFriends}
      {clickChannels}
      {clickLeaderboard}
    />
    {#if appState.includes(`${APPSTATE.CHANNELS}#`)}
      <div
        on:click={() => setAppState(APPSTATE.CHANNELS)}
        on:keydown={() => setAppState(APPSTATE.CHANNELS)}
      >
        <Chat
          channel={selectedChannel}
          on:view-profile={openIdProfile}
          on:add-friend={addFriend}
          on:invite-to-game={pong.inviteToGame}
          on:send-message={openDirectChat}
          on:return-home={resetAppState}
        />
      </div>
    {/if}
    {#if appState.includes(APPSTATE.CHANNELS)}
      <div
        class="{appState !== APPSTATE.CHANNELS ? 'hidden' : ''}"
        on:click={resetAppState}
        on:keydown={resetAppState}
      >
        <Channels bind:this={chan} onSelectChannel={handleSelectChannel} />
      </div>
    {/if}
    {#if appState === APPSTATE.LEADERBOARD}
      <div on:click={resetAppState} on:keydown={resetAppState}>
        <Leaderboard />
      </div>
    {/if}
    {#if appState === APPSTATE.FRIENDS}
      <div on:click={resetAppState} on:keydown={resetAppState}>
        <Friends />
      </div>
    {/if}
    {#if appState === APPSTATE.HISTORY}
      <div on:click={resetAppState} on:keydown={resetAppState}>
        <MatchHistory />
      </div>
    {/if}
    {#if appState === APPSTATE.HISTORY_ID}
      <div
        on:click={() => setAppState(APPSTATE.PROFILE)}
        on:keydown={() => setAppState(APPSTATE.PROFILE)}
      >
        <MatchHistory username={profileUsername} />
      </div>
    {/if}
    {#if appState === APPSTATE.PROFILE}
      <div on:click={resetAppState} on:keydown={resetAppState}>
        <Profile {gamePlaying} on:view-history={() => setAppState(APPSTATE.HISTORY_ID)} />
      </div>
    {/if}
    {#if appState === APPSTATE.PROFILE_ID}
      <div
        on:click={() =>
          setAppState(APPSTATE.CHANNELS + "#" + selectedChannel.name)}
        on:keydown={() =>
          setAppState(APPSTATE.CHANNELS + "#" + selectedChannel.name)}
      >
        <Profile
          {gamePlaying}
          username={profileUsername}
          on:view-history={() => setAppState(APPSTATE.HISTORY_ID)}
        />
      </div>
    {/if}

    {#if fakemenu}
      <FakeLogin bind:username={usernameFake} bind:ftId={ftIdFake} />
      <button on:click={impersonate}>Impersonate</button>
      <button on:click={() => (fakemenu = false)}>No impersonate</button>
    {:else}
      <Pong bind:gamePlaying={gamePlaying} bind:this={pong} {appState} {setAppState} {fakeUser} />
    {/if}
  {/if}

</Modal>
</div>

<style>
  :global(body) {
    background-color: #212529;
    color: #e8e6e3;
    margin: 0;
    padding: 0;
  }

  .login-div {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    gap: 1rem;
  }

  .img-42 {
    -webkit-filter: invert(100%);
    filter: invert(100%);
    width: 64px;
    height: 64px;
  }

  .login-button {
    display: inline-block;
    background-color: #198754;
    border: none;
    color: #fff;
    padding: 0.5rem 1rem;
    border-radius: 4px;
    cursor: pointer;
    font-size: 1rem;
    transition: background-color 0.2s ease-in-out;
  }

  .login-button:hover {
    background-color: #157347;
  }

  .login-button:focus {
    outline: none;
    box-shadow: 0 0 0 2px rgba(25, 135, 84, 0.25);
  }

  .hidden {
	display: none;
  }
</style>
