<template>
  <section class="lobby">
    <TopNav />
    <section v-if="!inRoom" class="body">
      <section id="info">
        <b-field label="Your name">
          <b-input :disabled="busy" v-model="playerName"></b-input>
        </b-field>
      </section>
      <section id="join">
        <header>
          <h1>Join someone's session</h1>
        </header>
        <b-field label="Session ID" class="only-full">
          <b-input :disabled="busy" v-model="joinSessionID"></b-input>
        </b-field>
        <div class="center submit only-full">
          <b-button
            type="is-primary"
            @click="join"
            class="wide"
            :disabled="busy || !canJoin"
          >
            Join
          </b-button>
        </div>
        <div class="only-mobile">
          <b-field class="full">
            <b-input
              :disabled="busy"
              placeholder="Session ID"
              v-model="joinSessionID"
            ></b-input>
            <p class="control">
              <b-button
                type="is-primary"
                @click="join"
                :disabled="busy || !canJoin"
              >
                Join
              </b-button>
            </p>
          </b-field>
        </div>
      </section>
      <section id="host">
        <header>
          <h1>Host a new session</h1>
        </header>
        <div class="columns">
          <div class="column">
            <b-field label="Max players">
              <b-numberinput
                :disabled="busy"
                controls-position="compact"
                v-model="hostMaxPlayers"
                min="2"
                max="8"
              ></b-numberinput>
            </b-field>
          </div>
          <div class="column">
            <b-field label="Password">
              <b-input :disabled="busy" v-model="hostPassword"></b-input>
            </b-field>
          </div>
        </div>

        <div class="center">
          <b-button
            :disabled="busy"
            type="is-primary"
            @click="create"
            class="wide"
          >
            Create
          </b-button>
        </div>
      </section>
    </section>
    <section class="room" v-else>
      <section class="info">
        Invite your friends:
        <span class="selectable"
          ><a :href="inviteLink">{{ inviteLink }}</a></span
        >
      </section>
      <section class="chat"></section>
      <section class="players">
        <header>Players</header>
        <ul>
          <li class="selectable" v-for="player in players" :key="player.name">
            {{ player.name }}
          </li>
        </ul>
      </section>
      <section class="player-options">
        <b-field>
          <b-input :disabled="busy" v-model="wantedName"></b-input>
          <p class="control">
            <b-button
              @click="changeName"
              type="is-primary"
              :disabled="!nameAvailable"
              >Change name</b-button
            >
          </p>
        </b-field>
        <b-button type="is-danger">Leave room</b-button>
      </section>
    </section>
  </section>
</template>

<style lang="scss" scoped>
@import "@/assets/scss/_variables.scss";

.lobby {
  background: url("../assets/images/backgrounds/menubg.webp") center;
  background-repeat: no-repeat;
  background-size: cover;
  height: 100vh;
  display: flex;
  flex-flow: column;
}

.body {
  flex: 1;
  display: grid;
  padding: 10px;
  padding-top: 0;
  grid-template: 150px 1fr / 1fr 1fr;

  #info {
    grid-row: 1;
    grid-column: 1 / end;
  }

  #join,
  #host {
    grid-row: 2;
  }

  #join {
    grid-column: 2;
  }
  #host {
    grid-column: 1;
  }

  section {
    margin: 10px;
    border: 1px solid rgba($white, 20%);
    border-radius: 10px;
    padding: 20px;
    header {
      font-family: $fantasy;
      h1 {
        text-align: center;
        font-size: 18pt;
      }
      margin-bottom: 20px;
    }
  }
}

.wide {
  min-width: 30%;
  margin: 10px auto;
}

.full {
  width: 100%;
  margin: 10px;
}

.center {
  width: 100%;
  text-align: center;
}

.full-btn {
  flex: 1;
  :global(.button) {
    width: 100%;
  }
}

.room {
  padding: 10px 20px;
  margin: 10px;
  border: 1px solid rgba($white, 20%);
  border-radius: 10px;
  display: grid;
  grid-template: 50px 1fr / 200px 1fr 300px;

  .info {
    grid-column: 1 / max;
    grid-row: 1;
  }

  .players {
    header {
      font-weight: bold;
      margin-bottom: 5px;
    }
    grid-row: 2 / max;
    grid-column: 1;
  }

  .chat {
    grid-row: 2 / max;
    grid-column: 2;
  }

  .player-options {
    grid-row: 2 / max;
    grid-column: 3;
  }
}

.only-mobile {
  display: none;
}

.selectable {
  user-select: all;
}

@media (max-width: 500px) {
  .only-full {
    display: none;
  }
  .only-mobile {
    display: inherit;
  }
  .body {
    display: flex;
    flex-direction: column;
    section {
      padding: 10px;
      header h1 {
        font-size: 14pt;
      }
    }
  }

  .room {
    display: flex;
    flex-flow: column;
    & > * {
      padding: 10px;
    }
  }
}
</style>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import TopNav from "@/components/Navigation/TopNav.vue";
import {
  StartServerOptions,
  ConnectOptions,
  PlayerEntry
} from "@/store/network/types";
import { Action, Getter } from "vuex-class";
import { Client, NetworkMessage } from "@/network";

const networkNS = { namespace: "network" };

@Component({
  components: {
    TopNav
  }
})
export default class Lobby extends Vue {
  private playerName!: string;
  private hostMaxPlayers!: number;
  private hostPassword!: string;
  private joinSessionID!: string;
  private wantedName!: string;

  @Action("startServer", networkNS)
  private startServer!: (options: StartServerOptions) => void;

  @Action("sendMessage", networkNS)
  private sendMessage!: (message: NetworkMessage) => void;

  @Action("connect", networkNS)
  private connect!: (options: ConnectOptions) => void;

  @Getter("inRoom", networkNS)
  private inRoom!: boolean;

  @Getter("busy", networkNS)
  private busy!: boolean;

  @Getter("sessionID", networkNS)
  private sessionID!: string | null;

  @Getter("players", networkNS)
  private players!: PlayerEntry[];

  private data() {
    const playerName =
      "Guest-" +
      Math.random()
        .toString()
        .slice(2, 8);
    return {
      playerName,
      hostMaxPlayers: 8,
      hostPassword: "",
      joinSessionID: "",
      wantedName: playerName
    };
  }

  private mounted() {
    if ("id" in this.$route.params) {
      this.joinSessionID = this.$route.params.id;
      this.join();
    }
  }

  private async create() {
    this.wantedName = this.playerName;
    this.startServer({
      playerInfo: {
        name: this.playerName
      },
      roomInfo: {
        max_players: this.hostMaxPlayers,
        password: this.hostPassword
      }
    });
  }

  private async join() {
    this.wantedName = this.playerName;
    this.connect({
      serverID: this.joinSessionID,
      playerInfo: {
        name: this.playerName
      }
    });
  }

  private async changeName() {
    this.sendMessage({
      kind: "rename",
      oldname: this.playerName,
      newname: this.wantedName
    });
  }

  private get canJoin(): boolean {
    return this.joinSessionID != "";
  }

  private get inviteLink(): string {
    let subpath = "";
    const joinIndex = location.pathname.indexOf("/join");
    if (joinIndex > 0) {
      subpath = location.pathname.substring(0, joinIndex);
    }
    const lobbyIndex = location.pathname.indexOf("/lobby");
    if (lobbyIndex > 0) {
      subpath = location.pathname.substring(0, lobbyIndex);
    }
    return `${location.origin}${subpath}/join/${this.sessionID}`;
  }

  private get nameAvailable(): boolean {
    return (
      this.wantedName != "" &&
      !this.players.find(p => p.name == this.wantedName)
    );
  }
}
</script>
