var table = d3.select('#chart');

// { environments: [ { name, date, version?, percent, scores, maxscore } ]
// , tests: [ { id, name[], url? } ]
// , results: [[ {status: pass|fail, column: #, message?, stacktrace?, raw?} ]]
// }
d3.json('tap.json', function(json) {
  window.json = json;

  function score(browser, i) {
    var res = json.results
      , max = res.length
      , n   = res.filter(function(t) { return t[i].status == 'pass'; }).length;
    browser.percent = 100 * (n / max) + '%';
    browser.maxscore = max;
    browser.score = n;
    return browser;
  }

  // d3.selectAll('#chart thead th').style('background-image',function(d,i){console.log(i);if(!d)return;return '-webkit-linear-gradient(bottom, #'+(i&1?'f0f0f0':'fff')+' '+d.percent+',rgba(255, 0, 0, 0.3) '+d.percent+')';})

  // expand the "0" short form to { status: 'pass' } (and set the column # info)
  var results = json.results.map(function(row) {
                  return row.map(function(d,i) {
                    if (d) d.status = 'fail';
                    else d = { status:'pass' };
                    d.column = i + 1;
                    return d;
                  });
                })

  /* [ { key: "Firefox"
       , values: [ { its different versions } ]
       }
     , ... the other renderers
     ] */
    , browsers = d3.nest()
        .key(function(d) { return d.name.toLowerCase(); })
      .entries(json.environments = json.environments.map(score))

    , colgroups = [{ key: "test-names", values:[] }].concat(browsers)
    ;

  json.results = results; // ease debugging

  table.attr('cols', 1 + json.environments.length);

  // grouping together all shown browsers by browser family
  var cg = table.selectAll('colgroup')
    .data(colgroups);
  cg.enter().append('colgroup')
      .attr('class', function(d) { return d.key; })
    //.attr('span', function(d) { return d.values.length || undefined; })
      .selectAll('col')
        .data(function(d) { return d.values; })
        .enter().append('col')
          .attr('title', function(d) { return d.date; })
          .text(function(d) { return d.version; }) // NOP, when no version given
    ;

  var thead = table.select('thead')
    , tr    = thead.select('tr')
    , legend = thead.select('th');
  table.node().appendChild(thead.node()); // needs to be after the <colgroups>

  // the browser name headers
  var ths = window.ths = thead.select('tr').selectAll('th')
        .data([null].concat(json.environments))
      .enter().append('th')
        .attr('class', function(d) { return d && d.type; }) // NOP
      ;

  // name + date
  ths.append('div').text(function(d, i) { return d && d.name + ' '; })
     .append('span').text(function(d) { return d && d.date; })
    ;


  tr.node().appendChild(legend.node()); // put our legend at the far right

  function hovered_header(d) {
    var col = d3.event.target.__data__.column, th;
    if ((th = ths[0][col]))
      if ('classList' in th) th.classList.add('hover');
      else d3.select(th).classed('hover', true);
  }
  function leaving_header(d) {
    var col = d3.event.target.__data__.column, th;
    if ((th = ths[0][col]))
      if ('classList' in th) th.classList.remove('hover');
      else d3.select(th).classed('hover', false);
  }

  // all table rows on the main grid, and the default hover title for that line
  tr = window.tr = table
      .append('tbody').attr('class', 'data')
        .on('mouseover', hovered_header)
        .on('mouseout', leaving_header)
      .selectAll('tr').data(json.tests)
        .enter().append('tr')
          .attr('title', function(d) { return d.name.join(' -> '); })
    ;

  // grid columns: data from the tests
  tr.selectAll('td')
      .data(function(d, i) { return results[i]; })
    .enter().append('td')
      .attr('class', function(d) { return d.status; })
      .attr('title', function(d) { return d.message; })
    //.classed('died', function(d) { return d.crash; })
    ;

  // last column: the test id and name
  var group;
  tr.append('th')
      .classed('group', function(d) {
        var my_group = d.name.slice(0, 1).join('\t') // FIXME: 1 -> -1, perhaps?
          , was_same = my_group === group;
        group = my_group;
        return !was_same;
      })
    .append('a')
      .style('margin-left', function(d) { return (d.name.length - 1)*5 + 'px';})
      .attr('name', function(d) { return 'test-'+ d.id; })
      .attr('href', function(d) { return d && d.url || '#test-'+ d.id; })
      .text(function(d, i) { return d.name[d.name.length - 1]; })
      .attr('title', function(d, i) { return d.name.slice(0,-1).join(' -> '); })
    ;

  table.selectAll('td.pass, td.warn, td.fail').on('click', function(d) {
    if (d.message) {
      var msg = 'Message: '+ d.message;
      if (d.stacktrace)
        msg += '\n\nstack trace:\n'+ d.stacktrace;
      alert(msg);
    }
  });
});