// jshint asi:true

function scoreboardInit() {
  
  chartColors = [
    "rgb(255, 99, 132)",
    "rgb(255, 159, 64)",
    "rgb(255, 205, 86)",
    "rgb(75, 192, 192)",
    "rgb(54, 162, 235)",
    "rgb(153, 102, 255)",
    "rgb(201, 203, 207)"
  ]
  
  function update(state) {
    for (let rotate of document.querySelectorAll(".rotate")) {
      rotate.appendChild(rotate.firstElementChild)
    }
    
    let element = document.getElementById("rankings")
    let teamNames = state.TeamNames
    let pointsLog = state.PointsLog
  
    // Every machine that's displaying the scoreboard helpfully stores the last 20 values of
    // points.json for us, in case of catastrophe. Thanks, y'all!
    //
    // We have been doing some variation on this "everybody backs up the server state" trick since 2009.
    // We have needed it 0 times.
    let stateHistory = JSON.parse(localStorage.getItem("stateHistory")) || []
    if (stateHistory.length >= 20) {
      stateHistory.shift()
    }
    stateHistory.push(state)
    localStorage.setItem("stateHistory", JSON.stringify(stateHistory))
  
    let teams = {}
    let highestCategoryScore = {} // map[string]int
  
    // Initialize data structures
    for (let teamId in teamNames) {
        teams[teamId] = {
        categoryScore: {},        // map[string]int
        overallScore: 0,          // int
        historyLine: [],          // []{x: int, y: int}
        name: teamNames[teamId],
        id: teamId
      }
    }
  
    // Dole out points
    for (let entry of pointsLog) {
      let timestamp = entry[0]
      let teamId = entry[1]
      let category = entry[2]
      let points = entry[3]
      
      let team = teams[teamId]
  
      let score = team.categoryScore[category] || 0
      score += points
      team.categoryScore[category] = score
  
      let highest = highestCategoryScore[category] || 0
      if (score > highest) {
        highestCategoryScore[category] = score
      }
    }

    for (let teamId in teamNames) {
      teams[teamId].categoryScore = {}
    }
    
    for (let entry of pointsLog) {
      let timestamp = entry[0]
      let teamId = entry[1]
      let category = entry[2]
      let points = entry[3]
      
      let team = teams[teamId]
  
      let score = team.categoryScore[category] || 0
      score += points
      team.categoryScore[category] = score
  
      let overall = 0
      for (let cat in team.categoryScore) {
        overall += team.categoryScore[cat] / highestCategoryScore[cat]
      }
  
      team.historyLine.push({t: new Date(timestamp  * 1000), y: overall})
    }
  
    // Compute overall scores based on current highest
    for (let teamId in teams) {
      let team = teams[teamId]
      team.overallScore = 0
      for (let cat in team.categoryScore) {
        team.overallScore += team.categoryScore[cat] / highestCategoryScore[cat]
      }
    }
  
    // Sort by team score
    function teamCompare(a, b) {
      return a.overallScore - b.overallScore
    }
  
    // Figure out how to order each team on the scoreboard
    let winners = []
    for (let teamId in teams) {
      winners.push(teams[teamId])
    }
    winners.sort(teamCompare)
    winners.reverse()
    
    // Let's make some better names for things we've computed
    let winningScore = winners[0].overallScore
    let numCategories = Object.keys(highestCategoryScore).length
  
    // Clear out the element we're about to populate
    Array.from(element.childNodes).map(e => e.remove())
  
    let maxWidth = 100 / winningScore
    for (let team of winners) {
      let row = document.createElement("div")
      let ncat = 0
      for (let category in highestCategoryScore) {
        let catHigh = highestCategoryScore[category]
        let catTeam = team.categoryScore[category] || 0
        let catPct = catTeam / catHigh
        let width = maxWidth * catPct
        
        let bar = document.createElement("span")
        bar.classList.add("category")
        bar.classList.add("cat" + ncat)
        bar.style.width = width + "%"
        bar.textContent = category + ": " + catTeam
        bar.title = bar.textContent
  
        row.appendChild(bar)
        ncat += 1
      }
  
      let te = document.createElement("span")
      te.classList.add("teamname")
      te.textContent = team.name
      row.appendChild(te)
  
      element.appendChild(row)
    }
    
    let datasets = []
    for (let i in winners) {
      if (i > 5) {
        break
      }
      let team = winners[i]
      let color = chartColors[i % chartColors.length]
      datasets.push({
        label: team.name,
        backgroundColor: color,
        borderColor: color,
        data: team.historyLine,
        lineTension: 0,
        fill: false
      })
    }
    let config = {
      type: "line",
      data: {
        datasets: datasets
      },
      options: {
        responsive: true,
        scales: {
          xAxes: [{
            display: true,
            type: "time",
            time: {
              tooltipFormat: "ll HH:mm"
            },
            scaleLabel: {
              display: true,
              labelString: "Time"
            }
          }],
          yAxes: [{
            display: true,
            scaleLabel: {
              display: true,
              labelString: "Points"
            }
          }]
        },
        tooltips: {
          mode: "index",
          intersect: false
        },
        hover: {
          mode: "nearest",
          intersect: true
        }
      }
    }
    
    let chart = document.querySelector("#chart")
    if (chart) {
      let canvas = chart.querySelector("canvas")
      if (! canvas) {
        canvas = document.createElement("canvas")
        chart.appendChild(canvas)
      }
      
      let myline = new Chart(canvas.getContext("2d"), config)
      myline.update()
    }
  }
  
  function refresh() {
    fetch("state")
    .then(resp => {
      return resp.json()
    })
    .then(obj => {
      update(obj)
    })
    .catch(err => {
      console.log(err)
    })
  }

  function init() {
    let base = window.location.href.replace("scoreboard.html", "")
    let location = document.querySelector("#location")
    if (location) {
      location.textContent = base
    }
  
    setInterval(refresh, 60000)
    refresh()
  }
  
  init()
}

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", scoreboardInit)
} else {
  scoreboardInit()
}
