import { useState } from "react";
import {
  Button,
  Card,
  Col,
  Divider,
  Form,
  Input,
  InputNumber,
  Row,
  Select,
  Badge,
} from "antd";
import { red } from "@ant-design/colors";

import connection, {
  useConfig,
  useIsConnected,
  useRoom,
  useTimelineSongFileChanged,
} from "../lib/Connection";

import "../css/lobby.css";
import logo from "../img/via-logo.svg";
import haramlogo from "../img/harambee_logo.png";
import beer from "../img/beer.png";
import { RoomOptions } from "../types/types";

const { Option } = Select;

export interface PropType {
  currentUserReady: boolean;
  onCurrentUserReadyChange?: (ready: boolean) => void;
}

const Lobby = (props: PropType) => {
  // Form/control states.
  const [selectedRoomId, setSelectedRoomId] = useState(1);
  const [seekTime, setSeekTime] = useState(0);
  const [timelineName, setTimelineName] = useState(null);
  const [joiningLobby, setJoiningLobby] = useState(false);
  const [joinLobbyError, setJoinLobbyError] = useState(false);
  const [isPreloading, setIsPreloading] = useState(false);
  const timeline = useTimelineSongFileChanged();

  // Room and logic states.
  const isConnected = useIsConnected();
  const room = useRoom();
  const config = useConfig();

  const isLeader = room?.isLeader || false;
  const userCount = room?.userCount || 0;

  async function handleJoin() {
    await preloadAudio();
    connection.requestSetReady();
    props.onCurrentUserReadyChange?.(true);
  }

  async function applyRoomId(v: number) {
    setJoiningLobby(true);
    await connection.requestJoin(v);
    setJoiningLobby(false);
    setJoinLobbyError(!v);
  }

  function handleJoinRandomLobby() {
    connection.requestJoinRandom();
    setJoinLobbyError(false);
  }

  function handleTimelineNameSet(timelineName: any) {
    setTimelineName(timelineName);
    connection.setRoomOptions(
      new RoomOptions(
        seekTime * 1000 || 0,
        timelineName || room?.timelineName || ""
      )
    );
  }

  function handleSetSeekTime(seekTime: number) {
    setSeekTime(seekTime);
    connection.setRoomOptions(
      new RoomOptions(
        seekTime * 1000 || 0,
        timelineName || room?.timelineName || ""
      )
    );
  }

  function preloadAudio(): Promise<boolean> {
    setIsPreloading(true);
    const songFile = timeline?.songFile;

    if (!songFile) {
      return Promise.resolve(false);
    }

    return new Promise<boolean>((resolve) => {
      const audioElement = new Audio();
      audioElement.addEventListener("canplaythrough", () => {
        // 'canplaythrough' means the browser thinks it has buffered enough to play
        // until the end.
        setIsPreloading(false);
        resolve(true);
      });
      audioElement.src = songFile;
    });
  }

  const leaderConfig = (
    <Row justify="center">
      <Col>
        <Form
          layout="horizontal"
          labelCol={{ span: 8 }}
          wrapperCol={{ span: 24 }}
        >
          <Form.Item label="Starttijd">
            <Input
              type="number"
              suffix="sec"
              value={seekTime}
              onChange={(v) => handleSetSeekTime(parseInt(v.target.value) || 0)}
            />
          </Form.Item>

          <Form.Item label="Nummer">
            <Select
              defaultValue={(room && room.timelineName) || ""}
              onChange={(e) => handleTimelineNameSet(e)}
            >
              {config &&
                config.availableTimelines.map((item, i) => (
                  <Option key={item} value={item}>
                    {item}
                  </Option>
                ))}
            </Select>
          </Form.Item>
        </Form>

        <Button
          block
          type="primary"
          loading={isPreloading}
          onClick={handleJoin}
        >
          Start
        </Button>
      </Col>
    </Row>
  );

  const nonLeaderConfig = (
    <Row justify="center">
      <Col>
        <p>
          {room?.running ? "We luisteren naar" : "We gaan luisteren naar"}{" "}
          <b>{room && room.timelineName}</b> en
          {room?.running && <span> zijn al gestart!</span>}
          {!room?.running && (
            <span> starten op {(room?.seekTime || 0) / 1000} seconden</span>
          )}
        </p>

        <Button
          block
          type="primary"
          disabled={!room || props.currentUserReady}
          loading={isPreloading}
          onClick={handleJoin}
        >
          {room && props.currentUserReady
            ? "Wachten op het startsein"
            : "Kom erbij"}
        </Button>
      </Col>
    </Row>
  );

  return (
    <div className="lobby">
      <Row className="centurion-title" justify="center">
        <Col span={4} md={4}>
          <img
            src={beer}
            className={`beer beer-flipped ${
              isConnected ? "connected" : "connecting"
            }`}
            alt="beer"
          />
        </Col>
        <Col span={12} md={6}>
          Centurion!
        </Col>
        <Col span={4} md={4}>
          <img
            src={beer}
            className={`beer ${isConnected ? "connected" : "connecting"}`}
            alt="beer"
          />
        </Col>
      </Row>
      <Row>
        <Col className="hints" span={24}>
          <div>Honderd minuten...</div>
          <div>Honderd shots...</div>
          <div>Kun jij het aan?</div>
        </Col>
      </Row>
      <br />

      {!isConnected && (
        <Row justify="center">
          <Col className="lobby-connecting">
            <h2>Verbinden...</h2>
          </Col>
        </Row>
      )}

      {isConnected && (
        <Row justify="center">
          <Col xs={24} sm={16} md={12} xl={10}>
            <Card>
              <h3>
                Huidige lobby: <b>{room ? `#${room.id}` : "Geen lobby"}</b>
              </h3>

              {room && (
                <Row>
                  {userCount === 1 ? (
                    <span>Er is één gebruiker aanwezig.</span>
                  ) : (
                    <span>Er zijn {userCount} gebruikers aanwezig.</span>
                  )}
                </Row>
              )}

              <Row justify="center">
                {room?.users?.map((u) => (
                  <Badge
                    key={u.id}
                    status={u.readyToParticipate ? "success" : "error"}
                  />
                ))}
              </Row>

              {room && <Row>Deel de link met je vrienden om mee te doen!</Row>}

              <Divider />

              {room && (isLeader ? leaderConfig : nonLeaderConfig)}

              <Divider />

              <Row justify="center">
                <Col>
                  <InputNumber
                    style={{ width: "calc(100% - 150px)" }}
                    min={1}
                    max={100000}
                    value={selectedRoomId || room?.id || 0}
                    onChange={(v) => setSelectedRoomId(v || 0)}
                  />

                  <Button
                    style={{ width: "150px" }}
                    type="primary"
                    loading={joiningLobby}
                    onClick={async () => {
                      await applyRoomId(selectedRoomId);
                    }}
                  >
                    Ga naar die lobby
                  </Button>

                  {joinLobbyError && (
                    <span style={{ color: red[4] }}>
                      Die lobby bestaat niet
                    </span>
                  )}
                </Col>
              </Row>

              <Row justify="center">
                <span className={"lobby-options-or"}>of</span>
              </Row>

              <Row justify="center">
                <Col>
                  <Button
                    type="primary"
                    onClick={() => {
                      handleJoinRandomLobby();
                    }}
                  >
                    Join een nieuwe lobby
                  </Button>
                </Col>
              </Row>
            </Card>
          </Col>
        </Row>
      )}
      <img src={haramlogo} className="haram-logo" alt="haramlogo"/>
      <img src={logo} className="via-logo" alt="logo" />
    </div>
  );
};

export default Lobby;
