const firebase = require('firebase/app');
require('firebase/firestore');

const NUM_SCORES_DISPLAYED = 10;

/**
 * High score with Firebase cloud store.
 * Index: challengeId ASC difficulty ASC score DESC time ASC
 */
AFRAME.registerComponent('leaderboard', {
  schema: {
    apiKey: {type: 'string'},
    authDomain: {type: 'string'},
    databaseURL: {type: 'string'},
    projectId: {type: 'string'},
    storageBucket: {type: 'string'},
    messagingSenderId: {type: 'string'},

    challengeId: {default: ''},
    menuSelectedChallengeId: {default: ''},
    isVictory: {default: false}
  },

  init: function () {
    this.qualifyingIndex = undefined;
    this.scores = [];
    this.eventDetail = {scores: this.scores};
    this.addEventDetail = {scoreData: undefined, index: undefined};

    this.username = localStorage.getItem('supersaberusername') || 'Super Zealot';
    this.el.addEventListener('leaderboardusername', evt => {
      this.username = evt.detail.value;
      localStorage.setItem('supersaberusername', this.username);
    });
    this.el.addEventListener('leaderboardsubmit', this.addScore.bind(this));
  },

  update: function (oldData) {
    // Initialize Cloud Firestore through Firebase.
    if (!firebase.apps.length && this.data.apiKey) {
      firebase.initializeApp({
        apiKey: this.data.apiKey,
        authDomain: this.data.authDomain,
        databaseURL: this.data.databaseURL,
        projectId: this.data.projectId,
        storageBucket: this.data.storageBucket,
        messagingSenderId: this.data.messagingSenderId
      });
      this.firestore = firebase.firestore();
      this.firestore.settings({timestampsInSnapshots: true});
      this.db = this.firestore.collection('scores');
    }

    if (!oldData.isVictory && this.data.isVictory) {
      this.checkLeaderboardQualify();
    }

    if (this.data.menuSelectedChallengeId &&
        oldData.menuSelectedChallengeId !== this.data.menuSelectedChallengeId) {
      this.fetchScores(this.data.menuSelectedChallengeId);
    }

    if (this.data.challengeId && oldData.challengeId !== this.data.challengeId) {
      this.fetchScores(this.data.challengeId);
    }
  },

  addScore: function () {
    const state = this.el.sceneEl.systems.state.state;
    if (!state.isVictory) { return; }
    const scoreData = {
      challengeId: state.challenge.id,
      score: state.score.score,
      username: this.username,
      difficulty: state.challenge.difficulty,
      time: new Date()
    };
    this.db.add(scoreData);
    this.addEventDetail.scoreData = scoreData;
    this.el.emit('leaderboardscoreadded', this.addEventDetail, false);
  },

  fetchScores: function (challengeId) {
    const state = this.el.sceneEl.systems.state.state;
    const query = this.db
      .where('challengeId', '==', challengeId)
      .where(
        'difficulty', '==',
        state.menuSelectedChallenge.id
          ? state.menuSelectedChallenge.difficulty
          : state.challenge.difficulty)
      .orderBy('score', 'desc')
      .orderBy('time', 'asc')
      .limit(10);
    query.get().then(snapshot => {
      this.eventDetail.challengeId = challengeId;
      this.scores.length = 0;
      if (!snapshot.empty) {
        snapshot.forEach(score => this.scores.push(score.data()));
      }
      this.el.sceneEl.emit('leaderboard', this.eventDetail, false);
    }).catch(e => {
      console.error('[firestore]', e);
    });
  },

  /**
   * Is high score?
   */
  checkLeaderboardQualify: function () {
    const state = this.el.sceneEl.systems.state.state;
    const score = state.score.score;

    // If less than 10, then automatic high score.
    if (this.scores.length < NUM_SCORES_DISPLAYED) {
      this.qualifyingIndex = this.scores.length;
      this.el.sceneEl.emit('leaderboardqualify', this.scores.length, false);
      return;
    }

    // Check if overtook any existing high score.
    for (let i = 0; i < this.scores.length; i++) {
      if (score > this.scores[i].score) {
        this.qualifyingIndex = i;
        this.el.sceneEl.emit('leaderboardqualify', i, false);
        return;
      }
    }
  }
});

AFRAME.registerComponent('leaderboard-title', {
  schema: {
    leaderboardQualified: {default: false}
  },

  update: function () {
    const value = this.data.leaderboardQualified
      ? 'NEW HIGH SCORE!'
      : 'LEADERBOARD';
    this.el.setAttribute('text', 'value', value);
  }
});
