<!DOCTYPE html>
<meta charset="utf-8">

<link href="../src/nv.d3.css" rel="stylesheet" type="text/css">

<style>

body {
  overflow-y:scroll;
}

text {
  font: 12px sans-serif;
}

svg {
  display: block;
}

#chart1 svg {
  height: 500px;
  min-width: 100px;
  min-height: 100px;
/*
  margin: 50px;
  Minimum height and width is a good idea to prevent negative SVG dimensions...
  For example width should be =< margin.left + margin.right + 1,
  of course 1 pixel for the entire chart would not be very useful, BUT should not have errors
*/
}

</style>
<body>

  <div id="chart">
    <svg style="height: 500px;"></svg>
  </div>
  <div id="stream1" style="float: left; margin-left: 15px;">
    <div><h1>Stream #1</h1></div>
  </div>
  <div id="stream2" style="float: left; margin-left: 15px;">
    <div><h1>Stream #2</h1></div>
  </div>
  <div id="stream3" style="float: left; margin-left: 15px;">
    <div><h1>Stream #3</h1></div>
  </div>

<script src="../lib/d3.v3.js"></script>
<script src="../lib/crossfilter.js"></script>
<script src="../nv.d3.js"></script>
<script src="../src/tooltip.js"></script>
<script src="../src/utils.js"></script>
<script src="../src/models/legend.js"></script>
<script src="../src/models/axis.js"></script>
<script src="../src/models/scatter.js"></script>
<script src="../src/models/line.js"></script>
<script src="../src/models/lineWithFocusChart.js"></script>
<script src="stream_layers.js"></script>
<script>

extend = function(destination, source) {
    for (var property in source) {
    if (property in destination) { 
      if ( typeof source[property] === "object" &&
        typeof destination[property] === "object") {
          destination[property] = extend(destination[property], source[property]);
      } else {
        continue;
      }
    } else {
      destination[property] = source[property];
    };
    }
    return destination;
};

var rawData = testCrossfilterData();

nv.addGraph(function() {
  var chart = nv.models.lineWithFocusChart();

  chart.xAxis
      .tickFormat(d3.format(',f'));
  chart.x2Axis
      .tickFormat(d3.format(',f'));

  chart.yAxis
      .tickFormat(d3.format(',.2f'));
  chart.y2Axis
      .tickFormat(d3.format(',.2f'));

  chart.dispatch.on('brush', click);

  var data = normalizeData(rawData.datum, 
        [
        {
          name: 'Stream #1',
          key: 'stream1'
        },
        {
          name: 'Stream #2',
          key: 'stream2'
        },
        {
          name: 'Stream #3',
          key: 'stream3'
        }
        ]);
nv.log(data);
  d3.select('#chart svg')
      .datum(data)
    .transition().duration(500)
      .call(chart);

  nv.utils.windowResize(chart.update);

  return chart;
});

function click(e) {
  extent = e.extent;

  rawData.data.filter([extent[0], extent[1]]);
  streams("stream1");
  streams("stream2");
  streams("stream3");
}

function streams(key) {
  var topData = rawData.data.top(5);

  var stream = d3.select("div#" + key).selectAll(".stream-data")
      .data(topData, function(d) {
        return d.key;
      });

  stream
    .html(function(d) {
      return d[key];
    })

  stream.enter().append("div")
      .attr("class", "stream-data")
      .html(function(d) {
        return  d[key]; 
      })

  stream.exit().remove();

  stream.order();
}

function normalizeData(data, series) {
  var sort = crossfilter.quicksort.by(function(d) { return d.key; });
  var result = [];

  for (var i = 0; i < series.length; i++) {
    var seriesData = data.top(Infinity);
    var sorted = sort(seriesData, 0, seriesData.length);
    var values = [];

    seriesData.forEach(function(item, index) {
        values.push({x: item.key,  y: item.value[series[i].key]});
    });

    result.push({key: series[i].name, values: values, color: series[i].color});
  };

  return result;
};

function testCrossfilterData() {
  var data = crossfilter(testData());

  try {
    data.data = data.dimension(function(d) { return d.x; });
    data.datum = data.data.group(function(d) { return d; });
    data.datum.reduce(
      function (p, v) {
        p.count++;
        p.stream1 += v.stream1;
        p.stream2 += v.stream2;
        p.stream3 += v.stream3;
        return p;
      },
      function (p, v) {
        p.count--;
        p.stream1 -= v.stream1;
        p.stream2 -= v.stream2;
        p.stream3 -= v.stream3;
        return p;
      },
      function () {
        return {count: 0, stream1: 0, stream2: 0, stream3: 0};
      });

    data.stream1 = data.dimension(function(d) { return d.stream1; });
    data.stream1datum = data.data.group(function(d) { return d; });
    data.stream1datum.reduce(
      function (p, v) {
        p.count++;
        p.stream1 += v.stream1;
        p.stream2 += v.stream2;
        p.stream3 += v.stream3;
        return p;
      },
      function (p, v) {
        p.count--;
        p.stream1 -= v.stream1;
        p.stream2 -= v.stream2;
        p.stream3 -= v.stream3;
        return p;
      },
      function () {
        return {count: 0, stream1: 0, stream2: 0, stream3: 0};
      }
    );

    data.stream2 = data.dimension(function(d) { return d.stream2; });
    data.stream2datum = data.data.group(function(d) { return d; });
    data.stream2datum.reduce(
      function (p, v) {
        p.count++;
        p.stream1 += v.stream1;
        p.stream2 += v.stream2;
        p.stream3 += v.stream3;
        return p;
      },
      function (p, v) {
        p.count--;
        p.stream1 -= v.stream1;
        p.stream2 -= v.stream2;
        p.stream3 -= v.stream3;
        return p;
      },
      function () {
        return {count: 0, stream1: 0, stream2: 0, stream3: 0};
      }
    );

    data.stream3 = data.dimension(function(d) { return d.stream3; });
    data.stream3datum = data.data.group(function(d) { return d; });
    data.stream3datum.reduce(
      function (p, v) {
        p.count++;
        p.stream1 += v.stream1;
        p.stream2 += v.stream2;
        p.stream3 += v.stream3;
        return p; },
      function (p, v) {
        p.count--;
        p.stream1 -= v.stream1;
        p.stream2 -= v.stream2;
        p.stream3 -= v.stream3;
        return p;
      },
      function () {
        return {count: 0, stream1: 0, stream2: 0, stream3: 0};
      }
    );
  } catch (e) {
    nv.log(e.stack);
  }

  return data;
}

function testData() {
  var data1 = [];
  var data2 = [];
  var data3 = [];

  stream_layers(3,128,.1).map(function(layer, index) {
    layer.forEach(function(item, i) {
      var object = { x: item.x };
      object['stream' + (index + 1)] = item.y;
      eval('data' + (index + 1)).push(object);
    });
  });

  var data = extend(data1, data2);
  var result = extend(data, data3);

  return result;
}


</script>
