class Scoreboard {
  
  String dataSource; // nom du fichier csv
  Table table;
  boolean autoload = true; // chargement et rechargement automatique
  boolean display = true;
  float posX, posY, width, height; // position et dimensions de l'afficheur
  
  Scoreboard() {
    this.dataSource = "scoreboard.csv";
    this.setup();
  }
  Scoreboard(String dataSource) {
    this.dataSource = dataSource;
    this.setup();
  }
  
  void setup() {
    if (autoload) this.load();
    this.posX = 1548;
    this.posY = 0;
    this.width = 300;
    this.height = 118;
  }
  
  // charge ou génère le tableau des scores
  void load() {
    if (fileExists(this.dataSource)) {
      this.table = loadTable("data/"+this.dataSource, "header");
    } else {
      this.table = new Table();
      this.table.addColumn("equipe");
      this.table.addColumn("score");
      this.table.addColumn("tour");
      for (int i = 0 ; i < nombreEquipes; i++) {
        TableRow scoreEquipe = this.table.addRow();
        
        scoreEquipe.setInt("equipe", i+1);
        scoreEquipe.setInt("score", 0);
        scoreEquipe.setInt("tour", 0);
      }
    }
    
    // typage forcé pour que .sort() fonctionne sur la colonne score
    this.table.setColumnType("score", "int");
    this.table.setColumnType("tour", "int");
    this.dataIntegrityCheck();
  }
  
  // écrit le tableau des scores dans un .csv
  void save() {
    this.table = new Table();
    
    this.table.addColumn("equipe");
    this.table.addColumn("score");
    this.table.addColumn("tour");
    
    for (int i = 0 ; i < equipes.length; i++) {
      Equipe e = equipes[i];
      TableRow scoreEquipe = this.table.addRow();
      
      scoreEquipe.setInt("equipe", e.id+1);
      scoreEquipe.setInt("score", e.score);
      scoreEquipe.setInt("tour", e.tour);
    }
    
    saveTable(this.table, "data/"+this.dataSource, "csv");
  }
  
  void reloadFromDisk() {
    //println("reload from disk");
    this.load();
    this.applyScores();
  }
  
  int getScore(int i) {
    return this.table.getInt(i, "score");
  }
  
  int getTour(int i) {
    return this.table.getInt(i, "tour");
  }
  
  void applyScores() {
    for (TableRow row : this.table.rows()) {
      equipes[row.getInt("equipe")-1].setScore(row.getInt("score"));
      equipes[row.getInt("equipe")-1].setTour(row.getInt("tour"));
    }
  }

  void applyScore(int equipe, int score, int tour) {
    this.table.findRow(str(equipe+1), "equipe").setInt("score", score);
    this.table.findRow(str(equipe+1), "equipe").setInt("tour", tour);
  }
  
  Iterable <TableRow> findRows(String value, String name) {
    return this.table.findRows(value, name);
  }
  
  Iterable <TableRow> findEquipesByScore(int value) {
    return this.table.findRows(str(value), "score");
  }
  
  boolean mouseHover() {
    if (mouseX > this.posX && mouseX < this.posX + this.width && mouseY > this.posY && mouseY < this.posY + height) return true;
    return false;
  }
  
  void toggleDisplay() {
    this.display = !this.display;
  }
  
  // vérifier si les données chargées correspondent à ce qui est attendu
  void dataIntegrityCheck() {
    // vérification du nombre de lignes // équipes
    int rowCount = this.table.getRowCount();
    
    if (rowCount!=nombreEquipes) {
      // on gère seulement le cas où on a chargé plus de lignes que d'équipes voulues
      // le cas inverse n'est pas bloquant et se résoud tout seul
      if (rowCount>nombreEquipes) {
        // calcul de la différence
        int diff = rowCount - nombreEquipes;
        // suppression des dernières lignes jusqu'à revenir à l'équilibre
        for (int i = rowCount; i>rowCount-diff; i--) {
          this.table.removeRow(i-1);
          //println("Scoreboard.removeRow", i-1);
        }
      }
    }
  }
  
  void draw() {
    //if (!this.display) return;
    int count = 0;
    //int podium = 3;
    int margin = 60;
    float offsetX = this.posX;
    float offsetY = this.posY;
    float lastX = 0;
    rectMode(CORNER);
    
    fill(color(0, 0, 0, 100));
    stroke(color(0, 0, 0));
    strokeWeight(1);
    rect(this.posX, this.posY+20, this.width, this.height);
    
    // pour chaque score de 50 à 1
    for (int i=50; i>0; i--) {
      // on limite aux 5 premières équipes
      if (count==5) break;
      // récupération des équipes à ce score
      Iterable<TableRow> rowsIterable = this.findEquipesByScore(i);
      ArrayList<String> teams = new ArrayList<String>();
      for (TableRow row : rowsIterable) { teams.add(row.getString("equipe")); }
      
      // arrêter la boucle si on est hors du cadre d'affichage
      //if (offsetX-margin<=this.posX) break;
      // passer cette itération si aucune équipe à afficher
      if (teams.size()==0) continue;

      // affichage du score
      fill(color(0,0,0));
      rect(offsetX, offsetY+20, 55, 50);
      fill(color(240, 240, 80));
      stroke(color(0, 0, 0));
      strokeWeight(1);
      textFont(quicksandFont, 40);
      String text = str(count+1);
      // correction de positionnement horizontal
      //   selon largeur du texte
      //float localMarginX = (i<=9)? margin+14: (i>=40)? margin-8: margin;
      float localMarginX = count==0? 10: 0;
      //   selon nombre d'équipes à afficher pour ce score
      // localMarginX = (teams.size()>1)? localMarginX+((teams.size()-1)*margin)/2: localMarginX;
      //fill(color(0, 250, 0));
      text(text, offsetX+localMarginX, offsetY+margin);
      
      localMarginX = count==0? 20: 25;
      textFont(quicksandFont, 20);
      text = count==0? " er": "e";
      text(text, offsetX+localMarginX, offsetY+margin-16);
      
      // affichage des équipes
      for(int j=0; j<teams.size(); j++) {
        // correction de positionnement horizontal
        //   selon nombre d'équipes à afficher pour ce score
        float subLocalMarginX = ((teams.size()-j)*margin)-margin/2;
        //subLocalMarginX = (teams.size()>1)? localMarginX+((teams.size()-1)*margin)/2: localMarginX;
        fill(color(240, 240, 80));
        circle(offsetX+subLocalMarginX, offsetY+(margin*2)-12, 50);
        fill(color(0, 0, 0));
        textFont(quicksandFont, 32);
        //   selon largeur du texte
        subLocalMarginX = (int(teams.get(j))<=9)? (int(teams.get(j))==1)? subLocalMarginX-6: subLocalMarginX-8: (int(teams.get(j))>=40)? subLocalMarginX-20: subLocalMarginX-15;
        text(teams.get(j), offsetX+subLocalMarginX, offsetY+(margin*2));
        count++;
      }
      
      //line(offsetX-(margin*teams.size())-10, offsetY, offsetX-(margin*teams.size())-10, offsetY+this.height);
      lastX = offsetX+(margin*teams.size())-10;
      
      offsetX += margin*teams.size();
    }
    
    noFill();
    stroke(color(0, 0, 0));
    //rect(lastX, this.posY, margin*count, this.height);
  }
}
