import { Match, Show, Switch } from "solid-js";
import {
  TrackLoop,
  TrackReference,
  VideoTrack,
  isTrackReference,
  useEnsureParticipant,
  useIsMuted,
  useIsSpeaking,
  useTrackRefContext,
  useTracks,
} from "solid-livekit-components";

import { Track } from "livekit-client";
import { Channel } from "stoat.js";
import { css } from "styled-system/css";
import { styled } from "styled-system/jsx";

import { UserContextMenu } from "@revolt/app";
import { useUser } from "@revolt/markdown/users";
import {
  Avatar,
  Button,
  Column,
  IconButton,
  OverflowingText,
  Row,
  iconSize,
} from "@revolt/ui";

import MdHeadsetOff from "@material-design-icons/svg/outlined/headset_off.svg?component-solid";
import MdMicOn from "@material-design-icons/svg/outlined/mic.svg?component-solid";
import MdMicOff from "@material-design-icons/svg/outlined/mic_off.svg?component-solid";

import { InRoom, useVoice } from ".";

export function RoomParticipants() {
  const tracks = useTracks(
    [
      { source: Track.Source.Camera, withPlaceholder: true },
      { source: Track.Source.ScreenShare, withPlaceholder: false },
    ],
    { onlySubscribed: false },
  );

  return (
    <div
      class={css({
        gap: "0.8em",
        padding: "1.6em",

        minHeight: 0,
        overflowX: "hidden",
        overflowY: "scroll",

        display: "flex",
        flexWrap: "wrap",
        justifyContent: "center",

        // display: 'grid',
        // gridAutoRows:'1fr',
        // gridTemplateColumns:'repeat(auto-fill, minmax(0, 1fr))',
      })}
    >
      <TrackLoop tracks={tracks}>{() => <LeParticipant />}</TrackLoop>
    </div>
  );
}

export function FakeParticipants() {
  return (
    <div
      class={css({
        gap: "0.8em",
        padding: "1.6em",

        minHeight: 0,
        overflowX: "hidden",
        overflowY: "scroll",
        display: "grid",
        gridAutoRows: "1fr",
        gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))",
      })}
    >
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
      <Tile />
    </div>
  );
}

const Tile = styled("div", {
  base: {
    minWidth: "240px",
    maxWidth: "240px",
    display: "grid",
    aspectRatio: "16/9",
    transition: ".3s ease all",
    borderRadius: "var(--borderRadius-lg)",
    background: "#0001",
    overflow: "hidden",
    outlineWidth: "3px",
    outlineStyle: "solid",
    outlineOffset: "-3px",
    outlineColor: "transparent",
  },
  variants: {
    speaking: {
      yes: {
        outlineColor: "#23a559",
      },
    },
  },
});

export function LeParticipant() {
  const participant = useEnsureParticipant();
  const track = useTrackRefContext();
  const isMuted = useIsMuted({
    participant,
    source: Track.Source.Microphone,
  });
  const isSpeaking = useIsSpeaking(participant);

  const user = useUser(participant.identity);

  return (
    <Tile speaking={isSpeaking() ? "yes" : undefined}>
      {/*{participant.identity}<br/>muted? {isMuted() ? 'yes' : 'no'}*/}
      <Switch
        fallback={
          <div
            class={css({
              gridArea: "1/1",
              display: "grid",
              placeItems: "center",
            })}
            // yeah good enough lmao
            use:floating={{
              contextMenu: () => (
                <UserContextMenu user={user().user!} member={user().member!} />
              ),
            }}
          >
            <Avatar
              src={user().avatar}
              fallback={user().username}
              size={64}
              interactive={false}
            />
          </div>
        }
      >
        <Match
          when={
            isTrackReference(track) &&
            (track.publication?.kind === "video" ||
              track.source === Track.Source.Camera ||
              track.source === Track.Source.ScreenShare)
          }
        >
          <VideoTrack
            style={{ "grid-area": "1/1" }}
            trackRef={track as TrackReference}
            manageSubscription={true}
          />
        </Match>
      </Switch>
      <div
        class={css({
          minWidth: 0,
          gridArea: "1/1",
          display: "flex",
          flexDirection: "row",
          justifyContent: "space-between",
          alignItems: "end",
          padding: "2",
          fontSize: "0.8em",
          textShadow: isTrackReference(track) ? "1px 1px 4px black" : "",
          // color: isTrackReference(track) ? 'white' : 'black',
          color: "transparent",
          fill: isTrackReference(track) ? "white" : "black",
        })}
      >
        <span class={css({ minWidth: 0 })}>
          <OverflowingText>{participant.identity}</OverflowingText>
        </span>
        <Show when={isMuted()}>
          <div
            class={css({
              borderRadius: "100%",
              background: isTrackReference(track) ? "#0006" : "#0001",
              padding: "1",
            })}
          >
            <MdMicOff {...iconSize(20)} />
          </div>
        </Show>
      </div>
    </Tile>
  );
}

export function DemoWrapper(props: { channel: Channel }) {
  const voice = useVoice()!;

  const shouldShow = () => {
    const room = voice.room();
    return !room
      ? !!props.channel.server
      : voice.channel()?.id === props.channel.id;
  };

  return (
    <Switch>
      <Match when={shouldShow()}>
        <Demo channel={props.channel} />
      </Match>
    </Switch>
  );
}

export function Demo(props: { channel: Channel }) {
  const voice = useVoice()!;

  /**
   * Join voice call
   * copy pasted from channelheader
   * todo: make this consistnet
   */
  async function joinCall() {
    voice.connect(props.channel);
  }

  return (
    /*<div>
      state: {voice.state()}
      <br />
      <Switch
        fallback={
          <>
            <Button onPress={() => voice.disconnect()}>Disconnect</Button>
            <br />
            <Button onPress={() => voice.toggleMute()}>
              <Switch fallback="Muted">
                <Match when={voice.microphone()}>Unmuted</Match>
              </Switch>
            </Button>
            <br />
            <Button onPress={() => voice.toggleCamera()}>
              <Switch fallback="Camera">
                <Match when={voice.video()}>Sharing camera</Match>
              </Switch>
            </Button>
            <br />
            <Button onPress={() => voice.toggleScreenshare()}>
              <Switch fallback="Share screen">
                <Match when={voice.screenshare()}>Sharing screen</Match>
              </Switch>
            </Button>
          </>
        }
      >
        <Match when={voice.state() === "READY"}>
          <Button onPress={() => voice.connect()}>Connect</Button>
        </Match>
      </Switch>
    </div>*/
    <Column
      class={css({
        height: "400px",
      })}
    >
      {/* <FakeParticipants /> */}
      <Show when={voice.state() === "CONNECTING"}>
        <span>Connecting...</span>
      </Show>
      <InRoom>
        <RoomParticipants />
      </InRoom>
      <div
        class={css({
          flexGrow: 1,
        })}
      />
      <Row justify>
        <Actions>
          <Show when={voice.state() !== "READY"}>
            <div
              use:floating={{
                tooltip: props.channel.havePermission("Speak")
                  ? undefined
                  : {
                      placement: "top",
                      content: "No permission to speak",
                    },
              }}
            >
              <IconButton
                variant={voice.microphone() ? "filled" : "tonal"}
                isDisabled={!props.channel.havePermission("Speak")}
                onPress={() => voice.toggleMute()}
              >
                <Switch fallback={<MdMicOff {...iconSize(20)} />}>
                  <Match when={voice.microphone()}>
                    <MdMicOn {...iconSize(20)} />
                  </Match>
                </Switch>
              </IconButton>
            </div>
          </Show>

          <Show when={!props.channel.havePermission("Listen")}>
            <div
              use:floating={{
                tooltip: {
                  placement: "top",
                  content: "You are deafened (or missing Listen permission)",
                },
              }}
            >
              <IconButton variant="tonal" isDisabled>
                <MdHeadsetOff {...iconSize(20)} />
              </IconButton>
            </div>
          </Show>

          <Switch
            fallback={
              <Button onPress={() => voice.disconnect()}>Leave Call</Button>
            }
          >
            <Match when={voice.state() === "READY"}>
              <Button onPress={joinCall}>Join Call</Button>
            </Match>
          </Switch>

          <Show when={voice.state() !== "READY"}>
            {/* <Button variant="secondary">
              <MdHeadset {...iconSize(20)} />
            </Button> */}

            <div
              use:floating={{
                tooltip: {
                  placement: "top",
                  content: "Coming soon! 👀",
                },
              }}
            >
              <Button onPress={() => voice.toggleCamera()} isDisabled>
                <Switch fallback="Camera">
                  <Match when={voice.video()}>Sharing camera</Match>
                </Switch>
              </Button>
            </div>

            <div
              use:floating={{
                tooltip: {
                  placement: "top",
                  content: "Coming soon! 👀",
                },
              }}
            >
              <Button onPress={() => voice.toggleScreenshare()} isDisabled>
                <Switch fallback="Share screen">
                  <Match when={voice.screenshare()}>Sharing screen</Match>
                </Switch>
              </Button>
            </div>
          </Show>
        </Actions>
      </Row>
    </Column>
  );
}

const Actions = styled("div", {
  base: {
    display: "flex",
    gap: "2",
    padding: "2",
  },
});
