<template>
  <div id="player" class="flex-column" v-show="selectedTrack._id || selectedRadio._id">
    <input type="range" id="slider" min="0" max="100" step="0.1" v-model="selectedTrack.percent" @change="slideChanged"/>
    <div id="playerBar" class="flex-row">
      <div class="flex-row grow">
        <img class="cover pointer" :src="cover" :title="selectedTrack.parent.title" @click="gotoContainer" />
        <div v-if="selectedTrack._id" class="flex-column">
          <b>{{ selectedTrack.title }}</b>
          from
          <b>{{ selectedTrack.parent.title }}</b>
        </div>
        <div v-if="selectedRadio._id" class="flex-column">
          <b>{{ selectedRadio.name }}</b>
        </div>
      </div>
      <div id="playerControls" class="flex-row center">
        <button @click="switchShuffle" title="Shuffle mode" v-if="selectedTrack._id">
          <img src="static/icons/media-shuffle-dark.svg" v-show="$store.getters['player/shuffle']" class="small" />
          <img src="static/icons/media-consecutive-dark.svg" v-show="$store.getters['player/shuffle'] == false" class="small" />
        </button>
        <button @click="prevTrack" title="Back" v-if="selectedTrack._id">
          <awesome-icon icon="backward" />
        </button>
        <button @click="togglePlaying" :title="audio.paused ? 'Play' : 'Pause'">
          <awesome-icon icon="play" size="2x" v-if="audio.paused" />
          <awesome-icon icon="pause" size="2x" v-else />
        </button>
        <button @click="nextTrack" title="Forward" v-if="selectedTrack._id">
          <awesome-icon icon="forward" />
        </button>
        <button @click="switchRepeatType" title="Repeat mode" v-if="selectedTrack._id">
          <img src="static/icons/media-repeat-dark.svg" class="small" v-show="$store.getters['player/repeatType'] == 'all'" />
          <img src="static/icons/media-repeat-song-dark.svg" class="small" v-show="$store.getters['player/repeatType'] == 'one'" />
          <img src="static/icons/media-no-repeat-dark.svg" class="small" v-show="$store.getters['player/repeatType'] == 'none'" />
        </button>
      </div>
      <div class="flex-row ma-right hideOnMobilePortrait grow right">
        <span v-show="selectedTrack.title">{{ formatedP }}&nbsp;|&nbsp;{{ formatedD }}</span>
      </div>
    </div>
    <audio preload="auto" ref="audioControl" type="audio/mpeg" @ended="nextTrack" @canplay="play" @playing="playing" @durationchange="durationChanged" @timeupdate="timeUpdate" src></audio>
  </div>
</template>

<script>
export default {
  name: "PlayerControl",
  data() {
    return {
      audio: {},
      duration: 0,
      progress: 0,
      intervalProgress: 0,
      intervalState: 0,
      preConvert: false,
    };
  },

  mounted() {
    this.$nextTick(() => {
      this.audio = this.$refs.audioControl;
    });
    this.setMediaSession();
  },

  methods: {
    play() {
      this.audio.play();
    },
    pause() {
      this.audio.pause();

      window.clearInterval(this.intervalProgress);
      window.clearInterval(this.intervalState);

      this.pushState();
    },
    durationChanged() {
      this.duration = this.audio.duration;
    },
    playing() {
      window.clearInterval(this.intervalProgress);
      window.clearInterval(this.intervalState);

      this.intervalProgress = setInterval(() => {
        this.progress = this.audio.currentTime;
        this.selectedTrack.percent = (100 / this.duration) * this.progress;
      }, 500);

      if (this.currentUser._id) {
        this.intervalState = setInterval(() => {
          this.pushState();
        }, 10000);
      }
    },
    audioReset() {
      this.audio.pause();
      this.audio.src = "";
      this.$store.commit("tracks/resetSelectedTrack");
    },
    slideChanged() {
      this.audio.pause();
      this.$store.dispatch("tracks/skip");
    },
    skipToPercent(percent) {
      let was_paused = this.audio.paused;
      this.audio.pause();
      let currentTime = Math.floor((this.duration * percent) / 100);
      this.audio.currentTime = currentTime;
      this.progress = currentTime;
      if (!was_paused) {
        this.audio.play();
      }
    },
    skipToSecond(second) {
      let was_paused = this.audio.paused;
      this.audio.pause();
      this.audio.currentTime = second;
      if (!was_paused) {
        this.audio.play();
      }
    },
    playRadio(radio) {
      this.$store.commit("tracks/resetSelectedTrack");
      this.audio.pause();
      this.audio.src = radio.url;

      let item = {
        id: this.selectedRadio._id,
        covers: { cover128: this.selectedRadio.covers.cover128 },
        name: this.selectedRadio.name,
        type: "radio",
      };
      this.$store.dispatch("user/saveHistoryItem", item);
    },
    playTrack(track) {
      this.preConvert = false;
      this.$store.commit("radios/resetSelectedRadio");
      let url =
        this.$store.getters.server +
        "/api/tracks/" +
        track._id +
        "/stream/" +
        this.audioBpm;

      this.audio.pause();
      this.audio.src = url;

      if (this.currentTrackParent.progress) {
        if (this.currentTrackParent.progress.id == this.selectedTrack._id) {
          this.skipToSecond(this.currentTrackParent.progress.progress);
        }
        this.currentTrackParent.progress = undefined;
      }
      // Try to fix SAFARI
      this.audio.play();
    },
    pushHistoryItem() {
      if (!this.currentUser._id) {
        return;
      }

      let item = {
        id: this.currentTrackParent._id,
        type: this.currentTrackParentType,
      };
      if (item.type == "album") {
        item.title = this.currentTrackParent.title;
        item.covers = { cover128: this.currentTrackParent.covers.cover128 };
      } else {
        item.name = this.currentTrackParent.name;
        item.covers = { cover256: this.currentTrackParent.covers.cover256 };
      }
      this.$store.dispatch("user/saveHistoryItem", item);
      item = {
        id: this.selectedTrack._id,
        type: "track",
        title: this.selectedTrack.title,
        covers: { cover32: this.selectedTrack.parent.covers.cover32 },
        parent: {
          _id: this.selectedTrack.parent._id,
          title: this.selectedTrack.parent.title,
        },
      };
      this.$store.dispatch("user/saveHistoryItem", item);
    },
    nextTrack() {
      if (this.$store.getters["player/repeatType"] == "one") {
        this.skipToPercent(0);
        this.audio.play();
      } else {
        this.$store.dispatch("tracks/playNextTo", this.selectedTrack);
      }
    },
    prevTrack() {
      this.$store.dispatch("tracks/playPrevTo", this.selectedTrack);
    },
    togglePlaying() {
      if (!this.audio) {
        return;
      }
      if (!this.audio.paused) {
        this.pause();
      } else if (this.audio.src != "") {
        this.audio.play();
      }
    },
    reset(item) {
      let parentId = item.parent._id;
      if (item.parent.parent && item.parent.parent.tracks) {
        parentId = item.parent.parent._id;
      }
      this.$store.dispatch("user/resetProgress", parentId);

      window.clearInterval(this.intervalProgress);
      window.clearInterval(this.intervalState);
      if (!this.audio.paused) {
        this.audio.pause();
      }
      this.audio.src = "";
    },
    setMediaSession() {
      if ("mediaSession" in navigator) {
        let me = this;
        navigator.mediaSession.setActionHandler("play", function () {
          me.play();
        });
        navigator.mediaSession.setActionHandler("pause", function () {
          me.pause();
        });
        navigator.mediaSession.setActionHandler("seekto", function (details) {
          if (details.fastSeek && "fastSeek" in me.audio) {
            me.audio.fastSeek(details.seekTime);
            return;
          }
          me.audio.currentTime = details.seekTime;
        });
        navigator.mediaSession.setActionHandler("previoustrack", function () {
          me.prevTrack();
        });
        navigator.mediaSession.setActionHandler("nexttrack", function () {
          me.nextTrack();
        });
      }
    },
    gotoContainer() {
      if (this.currentUser._id) {
        switch (this.selectedTrack.parentType) {
          case "album":
            this.$router.push("/albums?id=" + this.selectedTrack.parent._id);
            break;
          case "artist":
            this.$router.push(
              "/artists?id=" + this.selectedTrack.parent.parent._id
            );
            break;
        }
      }
    },
    switchShuffle() {
      this.$store.dispatch("player/toggleShuffleMode");
      this.saveUserSettings();
    },
    switchRepeatType() {
      this.$store.dispatch("player/switchPlayerRepeatMode");
      if (!this.currentUser._id) {
        return;
      }
      this.saveUserSettings();
    },
    saveUserSettings() {
      if (!this.currentUser._id) {
        return;
      }
      this.$store.dispatch("user/savePlayerSettings");
    },
    pushState() {
      if (!this.currentUser._id) {
        return;
      }
      this.progress = this.audio.currentTime;
      let item = {
        id: this.selectedTrack._id,
        parentId: this.currentTrackParent._id,
        type: "track",
        progress: Math.round(this.progress)
      }
      this.$store.dispatch("user/saveProgress", item);
    },
    timeUpdate(event) {
      let percent = (event.target.currentTime / event.target.duration) * 100;
      if (percent > 10 && !this.preConvert) {
        this.preConvert = true;
        this.$store.dispatch("tracks/convertNextTo", {
          track: this.selectedTrack,
          rate: this.audioBpm,
        });
        this.pushHistoryItem();
      }
    },
  },
  computed: {
    cover() {
      if (this.selectedTrack.title != "") {
        let res = "/static/icons/dummy/album.svg";

        if (this.selectedTrack.parent.covers.cover64) {
          res = this.selectedTrack.parent.covers.cover64;
        }

        return res;
      }

      if (this.selectedRadio) {
        let res = "/static/icons/dummy/radio.svg";
        if (this.selectedRadio.covers.cover64) {
          res = this.selectedRadio.covers.cover64;
        }
        return res;
      }

      return "";
    },
    selectedTrack() {
      return this.$store.getters["tracks/selectedTrack"];
    },
    skipTo() {
      return this.selectedTrack.skipTo;
    },
    selectedRadio() {
      return this.$store.getters["radios/selectedRadio"];
    },
    currentTrackParent() {
      return this.$store.getters["tracks/selectedTrackContainer"];
    },
    currentTrackParentType() {
      let type = "album";
      if (
        this.selectedTrack.parent.parent &&
        this.selectedTrack.parent.parent.tracks
      ) {
        type = "artist";
      }
      return type;
    },
    currentUser() {
      return this.$store.getters["user/user"];
    },
    formatedD() {
      let m = Math.floor(this.duration / 60);
      let s = Math.floor(this.duration - m * 60);
      return (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
    },
    formatedP() {
      let m = Math.floor(this.progress / 60);
      let s = Math.floor(this.progress - m * 60);
      return (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
    },
    requestReplayTrack() {
      return this.$store.getters["player/requestReplayTrack"];
    },
    audioBpm() {
      return this.$store.getters["user/settings"].desktop_bpm || "128";
    },
  },
  watch: {
    requestReplayTrack() {
      this.skipToPercent(0);
    },
    skipTo(newVal) {
      if (newVal) {
        this.skipToPercent(newVal);
      }
    },
    selectedRadio(newVal) {
      if (newVal._id) {
        this.playRadio(newVal);
      } else {
        this.reset();
      }
    },
    selectedTrack(newVal, oldVal) {
      if (newVal._id) {
        this.playTrack(newVal);
      } else {
        this.reset(oldVal);
      }
    },
  },
};
</script>

<style scoped>
#player {
  background-color: var(--nav);
  max-height: 60px;
  height: 60px;
  z-index: 1001;
  box-shadow: 0 0px 4px var(--shadow);
}

#player .cover {
  width: 52px;
  margin-right: 4px;
}

#playerBar {
  overflow: hidden;
  max-height: 52px;
}

#playerBar>div {
  align-items: center;
}

#playerControls button {
  display: flex;
  padding: 4px 12px;
  align-self: stretch;
  border: none;
}

@media (max-width: 480px) {
  #player #playerControls {
    justify-content: end;
  }
}

input[type="range"] {
  border: none;
  overflow: hidden;
  -webkit-appearance: none;
  background-color: var(--secondary);
  height: 8px;
  padding: 0px;
}

input[type="range"]::-webkit-slider-runnable-track {
  height: 8px;
  -webkit-appearance: none;
  color: var(--primary);
}

input[type="range"]::-webkit-slider-thumb {
  width: 10px;
  -webkit-appearance: none;
  height: 8px;
  cursor: ew-resize;
  background: var(--dark);
  box-shadow: -4000px 0 0 4000px var(--primary);
}
</style>