<div class="container">
    <canvas id="game" width='641' height='641'></canvas>
    <div id="highscore">
      <h1>Who is the best ?</h1>
      <div class="bubble" id="bubble-save-score">
        <h2>
          Save your score :
          <span id="span-score">10588</span>
        </h2>
        <div class="input">
          <input type="text" placeholder="Pseudo">
          <button id="button-save-score" class="button">Save</button>
        </div>
      </div>
      <div class="bubble">
        <ol id="best-scores"></ol>
      </div>
    </div>
  </div>
body {
  padding: 0;
  margin: 0;
  background: #3FA8C6;
  color: #fff;
  font-family: 'Doppio One', sans-serif;
  text-shadow: 0 1px 0 rgba(0,0,0,.3); 
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.container {
  width: 80%;
  margin: 0 auto;
  //border : 1px solid;
}

#game {
  background: rgba(0,0,0,.1);
  border : 1px lightgray solid;
  float: left;
  margin-top: 2em
}

#highscore {
  position: relative;
  overflow: hidden;
  padding-bottom: 1em;
  padding-left: 40px;
}

h1, h2, h3, h4, h5, h6 {
  letter-spacing: -0.03em;
  font-size: 2em;
}

h1 { 
  margin: 0.667em 0 0;
  //padding-left: 0.5em;
  text-align: left; 
}

h2 {
  font-size: 1.5em;
}

.bubble {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.1);

  padding: 0.667em 1em;
  position: relative;
}

.bubble:after {
  content: "";
  position: absolute;
  
  width: 0; 
  height: 0; 
  border-top: 20px solid transparent;
  border-bottom: 20px solid transparent; 
  border-right: 20px solid white; 
  border-right-color: inherit;
  top: 50px;
  left: -20px;
}

#highscore ol {
  margin: 0;
  padding: 0;
  //overflow: hidden;
  list-style: none;
  counter-reset: item;
}

#highscore li {
  margin: 1.5% 1.5%;
  background: rgba(0,0,0,.1);
  border-color: rgba(0,0,0,.1);
  //border-radius: 2em;
}

#highscore li:before {
  //display: block;
  width: 2em;
  height: 2em;
  padding: 0.4em;
  margin: 0.667em auto 1em;
  
  content: counter(item);
  counter-increment: item;
  
  line-height: 2;
  text-align: center;
  
  background: rgba(0,0,0,.1);
  border-radius: 2em;
  box-shadow: inset 0 0 1em rgba(0,0,0,.1), 0 2px 2px rgba(255,255,255,.1);
}

.player {
  display: inline;
  padding: 0.3em;
  //width: 100%;
  //background: rgba(0,0,0,.1);
  //border-color: rgba(0,0,0,.1);
}

.playerscore {
  float: right;
  padding : 0.3em;
}

#bubble-save-score {
  display: none;
  //background-color: #5cb85c;
  margin-bottom: 30px;  
}

.input {
  font-size: 1em;
}

.button {
  background: rgba(0,0,0,.1);
}



//////////////////////////////////


@media screen and (max-width: 1200px) {
  .container {
    width: 90%;
    //margin: 0;
  }
}

@media screen and (max-width: 900px) {
  .container {
    width: auto;
    //margin: 0;
  }
  
  #game {
    float: none;
    margin-left: 40px;
  }
  
  .bubble:after {
    display: none;
  }
  
  #highscore {
  padding-right: 40px;
}
// On a un canvas de 641 * 641 px divisé en une grille de 40*40 cases
// Chaque case de la grille mesure 15*15 px
// On laisse 1px de vide entre chaque case

// =============================  TODO ==============================
// [ ] Donner une durée de vie aux pommes, pour quelle s'effacent 
//     automatiquement si elles n'ont pas était prises
//
// [X] Sauvegarder le meilleur score du joueur
// [ ] Sauvegarderle meilleur score et le pseudo dans un cookie en cas de reload de la page
//
// [X] Restart game
//
// [X] Enregistrement des bestScores sur Firebase
//
// [X] Afficher le formulaire de sauvegarde du score
//     seulement si score > bestScore
//
// [ ] Ne pas afficher l'aide si on a déjà joué
//
// [ ] Ajouter un curseur dans le formulaire de sauvegarde du score
// [ ] Faire clignotter ce curseur
//
// [ ] Mode hardcore avec les commandes inversées (touche H au démarrage)
//
// [ ] Les coins du serpent en triangle quand il tourne
// =================================================================

// ------ Initialisation du canvas ------
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

// ------ Initialisation de Firebase ------
let config = {
    apiKey: "AIzaSyCZakOnkwqfE5CHnR4n9rMz2gQ0SuhMcck",
    authDomain: "snakejs-85a40.firebaseapp.com",
    databaseURL: "https://snakejs-85a40.firebaseio.com",
    projectId: "snakejs-85a40",
    storageBucket: "snakejs-85a40.appspot.com",
    messagingSenderId: "296755417289"
  };
firebase.initializeApp(config);
let database = firebase.database();
let bestScoreRef = database.ref('best_score');

// ------ Classe Snake ------
class Snake {
  constructor () {
    this.head = [20,20];
    this.tail = [[22, 20], [21, 20]];
    this.direction = [-1, 0];
    this.width = 15;
    this.red = 'rgb(200, 0, 0)';
    this.grey = 'rgb(211, 211, 211)';
    this.color = this.grey;
    this.level = 1;
  }
  
  drawSquare (x, y, color = this.grey) {
    ctx.fillStyle = color;
    ctx.fillRect(x*(1+this.width), y*(1+this.width), this.width, this.width);
  }
  
  draw () {
    this.drawSquare(this.head[0], this.head[1], this.color)
    for (let coord of this.tail) {
      this.drawSquare(coord[0], coord[1],this.color);
    }
  }
  
  move () {
    for (let i = 0; i < this.tail.length - 1; i++) {
      this.tail[i] = this.tail[i + 1];
    }
    this.tail[this.tail.length - 1] = this.head;
    let newHeadX = this.head[0]+this.direction[0];
    let newHeadY = this.head[1]+this.direction[1];
    if (newHeadX === -1) {newHeadX = 39;}
    if (newHeadX === 40) {newHeadX = 0;}
    if (newHeadY === -1) {newHeadY = 39;}
    if (newHeadY === 40) {newHeadY = 0;}
    this.head = [newHeadX, newHeadY];
  }
  
  grow () {
    // fait grandir le serpent d'un carré depuis la tête
    this.tail.push(this.head);
    let newHeadX = this.head[0]+this.direction[0];
    let newHeadY = this.head[1]+this.direction[1];
    if (newHeadX === -1) {newHeadX = 39;}
    if (newHeadX === 40) {newHeadX = 0;}
    if (newHeadY === -1) {newHeadY = 39;}
    if (newHeadY === 40) {newHeadY = 0;}
    this.head = [newHeadX, newHeadY];   
  }
  
  reduce () {
    //efface le dernier carré de la queue, taille mini du serpent = 3 carrés
    if (this.tail.length > 2) {
      let newTail = [];
      for (let i = 1; i < this.tail.length; i++) {
        newTail.push(this.tail[i]);
      }
      this.tail = newTail;
    }
  }
  
  distance (x, y) {
    // Donne la distance entre la tete du serpent et un point sur la grille
    let xSnake = this.head[0];
    let ySnake = this.head[1];
    return Math.sqrt(Math.pow(x - xSnake, 2) + Math.pow(y - ySnake, 2));
  }
  
  eat (apples) {
    // Le serpent mange il une pomme?
    //console.log(apples);
    let response = [false];
    for (let apple of apples) {
      let d = this.distance(apple[0], apple[1]);
      //console.log(d);
      if (d < 1) {response = [true]; response.push(apple);}
    }
    //console.log(response);
    return response;
  }
  
  crash (walls) {
    // Le serpent se crash t il sur un mur? ou sur sa queue?
    let response = false;
    let obstacles = [];
    obstacles = this.tail.concat(walls);
    for (let obstacle of obstacles) {
      let d = this.distance(obstacle[0], obstacle[1]);
      if (d < 1) {response = true;}
    }
    return response;
  }
}

// ------ Classe Apple ------
class Apple {
  constructor () {
    this.green = 'rgb(186, 218, 85)';
    this.orange = 'rgb(255, 165, 0)';
    this.red = 'rgb(200, 0, 0)';
    this.width = 15;
    this.apples = [];
    this.maxApple = 1;
    this.maxGenerate = 1;
    this.level = 1;
  }
  
  drawCircle (x, y, color = this.green) {
    ctx.fillStyle = color;
    //ctx.fillRect(x*(1+this.width), y*(1+this.width), this.width, this.width);
    ctx.beginPath();
    ctx.arc(x*(1+this.width)+this.width/2, y*(1+this.width)+this.width/2, this.width/2, 0, Math.PI * 2, true);
    ctx.fill();
  }
  
  generate () {
    //console.log('generate apple');
    if (this.apples.length < this.maxApple*this.level) {
      //let nbre = Math.floor((Math.random() * this.maxGenerate*this.level/3) + 1);
      let nbre = Math.floor((Math.random() * this.maxGenerate*this.level) + 1);
      //console.log(nbre);
      for (let i = 0; i < nbre; i++) {
        let X = Math.floor((Math.random() * 38) + 1);
        let Y = Math.floor((Math.random() * 38) + 1);
        let appleLevel = 0; // level 0 (vert) par defaut
        let percentage = Math.floor((Math.random() * 100) + 1);
        if (percentage <= 10*(this.level-1)) {appleLevel = 1;} // orange
        if (percentage <= 5*(this.level-1)) {appleLevel = 2;} // rouge
        let newApple = [X, Y, appleLevel];
        //console.log(newApple);
        this.apples.push(newApple);
      }
    }
  }
  
  delete (oneApple) {
    //efface une pomme du tableau apples
    let newApples = [];
    for (let apple of this.apples) {
      if (apple[0] !== oneApple[0] && apple[1] !== oneApple[1]) {
        newApples.push(apple);
      }
    }
    this.apples = newApples;
  }
  
  draw () {
    for (let apple of this.apples) {
      let color = this.green;
      if (apple[2] === 1) {color = this.orange;}
      if (apple[2] === 2) {color = this.red;}
      this.drawCircle(apple[0], apple[1], color);
    }
  }
}

// ------ Classe Wall ------
class Wall {
  constructor () {
    this.darkGrey = 'rgb(77, 77, 77)';
    this.level = 1;
    this.width = 15;
    this.walls = [];
    this.leftWalls = [];
    this.rightWalls = [];
    this.topWalls = [];
    this.bottomWalls = [];
  }
  
  drawSquare (x, y, color = this.darkGrey) {
    ctx.fillStyle = color;
    ctx.fillRect(x*(1+this.width), y*(1+this.width), this.width, this.width);
  }
  
  draw () {
    for (let wall of this.walls) {
      this.drawSquare(wall[0], wall[1],this.color);
    }
  }
  
  expand () {
    // Augmente la taille des murs
    if (this.level === 2) {
      let position = Math.floor((Math.random() * 35));
      //console.log(position);
      for (let i = 0; i <5; i++) {this.leftWalls.push([0, position+i]);}
      //console.log(this.leftWalls);
    }
    if (this.level === 3) {
      let position = Math.floor((Math.random() * 35));
      //console.log(position);
      for (let i = 0; i <5; i++) {this.topWalls.push([position+i, 0]);}
      //console.log(this.topWalls);
    }
    if (this.level > 3 && this.level <= 10) {
      // On ajoute 5 murs sur tous les cotés
      let indexTop = this.topWalls[this.topWalls.length-1][0];
      let indexLeft = this.leftWalls[this.leftWalls.length-1][1];
      //console.log('index : ' + index);
      for (let i = 1; i <= 5; i++) {
        if ((indexTop+i) > 39) {indexTop = -i;}
        if ((indexLeft+i) > 39) {indexLeft = -i;}
        this.topWalls.push([indexTop+i, 0]);
        this.leftWalls.push([0, indexLeft+i]);
      }
    }
    //Recopie des murs de gauche sur la droite
    this.rightWalls = [];
    for (let wall of this.leftWalls) {this.rightWalls.push([39, wall[1]]);}
    // Recopie des murs du haut en bas
    this.bottomWalls = [];
    for (let wall of this.topWalls) {this.bottomWalls.push([wall[0], 39]);}
    // Recopie de tous les murs
    this.walls = [];
    this.walls = this.leftWalls.concat(this.topWalls).concat(this.rightWalls).concat(this.bottomWalls);
  }
}

// ------ Classe Text ------
class Text {
  constructor () {
    this.grey = 'rgb(211, 211, 211)';
    this.red = 'rgb(255, 0, 0)';
  }
  
  drawBegin () {
    ctx.font = '48px Doppio One';
    ctx.textAlign = 'center';
    ctx.fillStyle = this.grey;
    let pos = 260;
    ctx.fillText('Press ENTER to start', 320, pos);
    ctx.font = '20px Doppio One';
    ctx.fillText('Le serpent grandi tout seul de plus en plus vite', 320, pos+40);
    ctx.fillText('Les pommes réduisent la taille du serpent', 320, pos+40+30);
    ctx.fillText('Le serpent préfère les pommes mûres rouges au pomme vertes', 320, pos+40+30+30);
    ctx.fillText('Le serpent peut sortir de l\'aire de jeu', 320, pos+40+30+30+30);
    ctx.fillText('Mais attention des murs apparaissent au fil du jeu', 320, pos+40+30+30+30+30);
    ctx.font = '28px Doppio One';
    ctx.fillText('Good Luck !!', 320, pos+40+30+30+30+30+40);
  }
  
  drawLevel (level) {
    ctx.font = '14px Doppio One';
    ctx.textAlign = 'left';
    ctx.fillStyle = this.grey;
    ctx.fillText('Level : ' + level, 10, 15);
  }
  
  drawScore (score) {
    ctx.font = '14px Doppio One';
    ctx.textAlign = 'left';
    ctx.fillStyle = this.grey;
    ctx.fillText('Score : ' + score, 90, 15);
  }
  
  drawPlayerName (playerName) {
    ctx.font = '14px Doppio One';
    ctx.textAlign = 'center';
    ctx.fillStyle = this.grey;
    ctx.fillText(playerName, 320, 15);
  }
  
  drawBestScore (bestScore) {
    ctx.font = '14px Doppio One';
    ctx.textAlign = 'right';
    ctx.fillStyle = this.grey;
    ctx.fillText('Best score : ' + bestScore, 540, 15);
  }
  
  drawGameOver (score, playerName, bestScore) {
    ctx.font = '72px Doppio One';
    ctx.textAlign = 'center';
    ctx.fillStyle = this.grey;
    ctx.fillText('GAME OVER', 320, 220);
    ctx.font = '48px Doppio One';
    ctx.fillText('Score : ' + score, 320, 300);
    ctx.font = '20px Doppio One';
    if (score > bestScore) {
      ctx.fillText('Tappe ton pseudo pour sauvegarder ton score', 320, 360);
      ctx.fillText('ENTER pour sauvegarder', 320, 460);
      this.drawForm(playerName);
    } else {
      ctx.fillText('Tappez r pour rejouer', 320, 360);
    }
  }
  
  drawForm (playerName = '') {
    ctx.clearRect(145, 380, 350, 50);
    ctx.fillStyle = this.grey;
    ctx.fillRect(145, 380, 350, 50);
    ctx.lineWidth = 4;
    ctx.strokeStyle = this.red;
    ctx.strokeRect(145, 380, 350, 50);
    ctx.fillStyle = this.red;
    ctx.font = '28px Doppio One';
    ctx.textAlign = 'center';
    ctx.fillText(playerName, 320, 413);
  }
  
  draw (level, score, playerName, bestScore) {
    this.drawLevel(level);
    this.drawScore(score);
    this.drawPlayerName(playerName);
    this.drawBestScore(bestScore);
  }
}

// ------ Classe Game ------
class Game {
  constructor (playerName = '', bestScore = 0) {
    this.tick = 200;
    this.tac = 0;
    this.appleEated = 0; // nombre de pommes mangées dans le level
    this.intervalId = [];
    this.gameStarted = false;
    this.gameOver = false;
    //this.gameOver = true;
    this.level = 1;
    this.score = 0;
    this.mode = 'normal';
    this.playerName = playerName || '';
    //this.playerName = 'Nikookni';
    this.bestScore = bestScore || 0;
    this.snake = new Snake();
    // nombre de pommes à manger avant augmentation de level
    this.appleToEat = 5;
    this.apple = new Apple();
    this.apple.generate();
    this.wall = new Wall();
    this.text = new Text();
    ctx.clearRect(0, 0, 641, 641);
    this.text.drawBegin();
    //this.text.drawGameOver(this.score, this.playerName, this.bestScore);
    this.text.draw(this.level, this.score, this.playerName, this.bestScore);
    document.addEventListener('keydown', (event) => {
      event.preventDefault();
      this.keyboard(event.key);
    }, false);
    console.log ('New game from Game Constuctor');
  }
  
  draw () {
    ctx.clearRect(0, 0, 641, 641);
    this.snake.draw();
    this.apple.draw();
    this.wall.draw();
    this.text.draw(this.level, this.score, this.playerName, this.bestScore);
    if (this.gameOver) {
      this.text.drawGameOver(this.score, this.playerName, this.bestScore);
      //this.showModal();
    }
  }
  
  gameEvent () {
    // Gère les événements du jeu
    // Le serpent mange une pomme?
    let eated = this.snake.eat(this.apple.apples);
    if (eated[0]) {
      console.log('Pomme mangée');
      this.appleEated++
      if (this.appleEated === this.appleToEat) {this.appleEated = 0; this.levelUp();}
      this.apple.delete(eated[1]);
      let appleLevel = eated[1][2];
      let tailReduction = 0;
      if (appleLevel === 0) {this.score = this.score+200; tailReduction = 2;}
      if (appleLevel === 1) {this.score = this.score+500; tailReduction = 5;}
      if (appleLevel === 2) {this.score = this.score+1000; tailReduction = 10;}
      for (let i = 0; i < tailReduction; i++) {this.snake.reduce();}
      this.apple.generate();
    }
    
    // Le serpent se crash sur un mur ou sur sa queue?
    if (this.snake.crash(this.wall.walls)) {
      console.log('Crash');
      this.snake.color = this.snake.red;
      this.gameOver = true;
      this.stop();
    }
  }
  
  speedUp () {
    // Accélère le jeu en fonction du level
    //this.start();
    if (this.level === 2) {this.start();}
    if (this.level === 4) {this.start();}
    if (this.level === 6) {this.start();}
    if (this.level === 8) {this.start();}
    if (this.level === 9) {this.start();}
    if (this.level === 10) {this.start();}
  }
  
  scoreUp () {
    // augmente le score en fonction du niveau
    if (!this.gameOver) {
      this.score = this.score + this.level;
    }
  }
  
  tailUp () {
    // augmente la queue du serpent en fonction du niveau
    let tacLimit = 13;
    if (this.level === 2) {tacLimit = 13}
    if (this.level === 3) {tacLimit = 12}
    if (this.level === 4) {tacLimit = 12}
    if (this.level === 5) {tacLimit = 11}
    if (this.level === 6) {tacLimit = 11}
    if (this.level === 7) {tacLimit = 10}
    if (this.level === 8) {tacLimit = 10}
    if (this.level === 9) {tacLimit = 9}
    if (this.level === 10) {tacLimit = 7}
    if (this.tac > tacLimit) {
      this.snake.grow();
      this.tac = 0;
      this.gameEvent();
    }
  }
  
  refresh () {
    this.snake.move();
    this.gameEvent();
    this.tac++
    this.tailUp();
    //this.gameEvent();
    //this.speedUp();
    this.scoreUp();
    this.draw();
  }
  
  start () {
    // Démarre le jeu
    // si cette fonction est appellée pendant le jeu la vitesse augmente 
    let newIntervalId = setInterval(() => {
      this.refresh();
    }, this.tick);
    this.intervalId.push(newIntervalId);
    console.log('intervalId : ' + this.intervalId);
  }
  
  stop () {
    for (let intId of this.intervalId) {
      clearInterval(intId);
      this.intervalId = [];
    }
    //console.log('intervalId after stop : ' + this.intervalId);
  }
  
  restartGame () {
    console.log('restartGame begin');
    //let lastPlayerName = this.playerName;
    //let lastBestScore = this.bestScore;
    //masterRestart(lastPlayerName, lastBestScore);
    
    this.tac = 0;
    this.appleEated = 0; // nombre de pommes mangées dans le level
    //this.intervalId = [];
    this.gameStarted = false;
    this.gameOver = false;
    this.level = 1;
    this.score = 0;
    this.mode = 'normal';
    this.snake = new Snake();
    // nombre de pommes à manger avant augmentation de level
    //this.appleToEat = 1;
    this.apple = new Apple();
    this.apple.generate();
    this.wall = new Wall();
    //this.text = new Text();
    ctx.clearRect(0, 0, 641, 641);
    this.text.drawBegin();
    //this.text.drawGameOver(this.score, this.playerName, this.bestScore);
    this.text.draw(this.level, this.score, this.playerName, this.bestScore);
    console.log ('New game from restartGame');
  }
  
  keyboard (key) {
    //console.log(key);
    // Démarrage du jeu 
    if (key === 'Enter' && !this.gameStarted && !this.gameOver) {
      this.gameStarted = true;
      this.start();
    }
    
    // Entrée du playerName dans le formulaire quand on est gameOver
    //console.log('gameOver : ' + this.gameOver);
    if (this.gameOver && (this.score > this.bestScore)) {
      //console.log(key);
      if (key !=='Enter') {
        let letterNumber = /^[0-9a-zA-Z]+$/;
        if (key.length === 1 && key.match(letterNumber)) {
          this.playerName += key;
          //console.log(this.playerName);
          this.text.drawForm(this.playerName);
        }
        if (key === 'Backspace') {
          //console.log('On efface');
          this.playerName = this.playerName.slice(0, -1);
          //console.log(this.playerName);
          this.text.drawForm(this.playerName);
        }
      }
      if (key ==='Enter') {
        //console.log('On sauvegarde le score');
        this.saveScore();
      }
    }
    
    if (this.gameOver && (this.score <= this.bestScore)) {
      //console.log(key);
      if(key === 'r') {
        //console.log('keyboard want to restartGame');
        this.restartGame();
      }
    }
    
    // Mouvement du serpent
    let oldDirection = this.snake.direction;
    if (key === 'ArrowLeft' && oldDirection[0] !== 1) {this.snake.direction = [-1, 0];}
    if (key === 'ArrowRight' && oldDirection[0] !== -1) {this.snake.direction = [1, 0];}
    if (key === 'ArrowUp' && oldDirection[1]!== 1) {this.snake.direction = [0, -1];}
    if (key === 'ArrowDown' && oldDirection[1] !== -1) {this.snake.direction = [0, 1];}
  }
  
  levelUp () {
    //augmente le niveau
    if (this.level < 10) {
      this.level++
      this.snake.level++
      this.apple.level++
      this.wall.level++
      this.wall.expand();
      this.speedUp();
      console.log('New level : ' + this.level);
    }
  }
  
  saveScore () {
    // sauvegarde du meilleur score
    if (this.score > this.bestScore) {
      this.bestScore = this.score;
      if(this.playerName.length < 1) {this.playerName = 'Anonymous'}
      this.saveScoreToFirebase(response => {
        if (response) {
          //console.log('saveScore want to restart game before Firebase save');
          this.restartGame();}
      });       
    } else {
      //console.log('saveScore want to restart game');
      this.restartGame();
    }
  }
  
  saveScoreToFirebase (callback) {
    // sauvegarde du score sur Firebase
    let data = {
      playerName: this.playerName,
      bestScore: this.bestScore,
      mode:this.mode
    };
    console.log('Saving score to Firebase... ');
    bestScoreRef.push(data)
      .then(function() {
        console.log('Save succeeded :');
        console.log(data);
        callback(true);
      })
      .catch(function(error) {
        console.log('Save failed');
      });
    
    //callback(true);
  }
}

// ------ Initialisation du jeu ------
let game = new Game();
//game.draw();

// ----- Affichage des bestScores ------
let playerScores = [];

const printBestScores = (playerScores) => {
  let bestScores = document.getElementById("best-scores");
  let html = '';
  for (let playerScore of playerScores) {
    html += `<li>
               <div class="player">
                 <span class="playername"><strong>${playerScore.playerName}</strong></span>
                 <span class="playerscore">${playerScore.bestScore}</span>
               </div>
            </li>`;
  }
  bestScores.innerHTML = html;
}

// ------- Récupération des bestScores sur Firebase -------
bestScoreRef.orderByChild("bestScore").on("child_added", function(snapshot) {
  let data = snapshot.val();
  console.log(data);
  playerScores.push(data);
  playerScores = _.orderBy(playerScores, ['bestScore'], ['desc']);
  printBestScores(playerScores);
});

External CSS

  1. https://fonts.googleapis.com/css?family=Doppio+One

External JavaScript

  1. https://www.gstatic.com/firebasejs/3.9.0/firebase.js
  2. https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js