
/* Utility functions */

function fmtChartJSPerso(config, value, fmt) {
  if (fmt == "ellipsize") {
    return ellipsize(value, 15);
  }
  if (fmt == "wrap") {
    return wrap_text(value, 15);
  }
  return value;
}

function capfirst(a) {
  if (! a.length) {
    return a;
  }
  if (a.charCodeAt(0) > 96 && a.charCodeAt(0) < 123) {
    return String.fromCharCode(a.charCodeAt(0) - 32) + a.slice(1);
  }
}

function days_to_string(days) {
    l = []
    if (days >= 1) {
        l.push(Math.floor(days).toString() + " jour(s) ")
        days -= Math.floor(days);
    }
    hours = days * 24;
    if (hours > 1) {
        l.push(Math.floor(hours).toString() + " heure(s)")
        hours -= Math.floor(hours);
    }
    minutes = hours * 60;
    if (l.length < 2 && minutes > 1) {
        l.push(Math.floor(minutes).toString() + " minutes(s)")
    }
    if (l.length) {
        return human_join(l);
    }
    return "Aucun";
}

function human_join(a) {
  /* Build french string for an enumeration */
  if (a.length == 0) {
    return '';
  }else if (a.length == 1) {
    return a[0].toString();
  } else {
    return a.slice(0, -1).join(', ') + ' et ' + a.slice(-1)[0];
  }
}

function wrap_text(s, width) {
  /* Wrap text after width characters */
  var words = s.split(" ");
  var s = "";
  var l = 0;
  for (var i = 0; i < words.length; i++) {
    l += 1 + words[i].length;
    if (l > width) {
      s = s + "\n";
      l = words[i].length;
    } else {
      s = s + " ";
    }
    s = s + words[i];
  }
  return s;
}

function ellipsize(s, length) {
  if (s.length > length) {
    return s.slice(0, length) + '…';
  }
  return s;
}

function spaced_hsla(i, n, s, l, a) {
    /* Compute a specific color in a hue gradient in hsla colorspace, used to generate color maps for
     * charts. */
    var h = 360 * i/n;
    return "hsla(" + h.toString() + ', ' + s.toString() + '%, ' + l.toString() + '%, ' + a.toString() + ')';
};

function toDataURL(canvas, filename) {
   /* Convert a canvas to a PNG image with a white background, and generate a data url for it */

   /* Temporary canvas with white background to print original canvas over */
   destinationCanvas = document.createElement("canvas");
   destinationCanvas.width = canvas.width;
   destinationCanvas.height = canvas.height;

   destCtx = destinationCanvas.getContext('2d');

   // create a rectangle with the desired color
   destCtx.fillStyle = "#FFFFFF";
   destCtx.fillRect(0, 0, canvas.width, canvas.height);

   // draw the original canvas onto the destination canvas
   destCtx.drawImage(canvas, 0, 0);
   var data = destinationCanvas.toDataURL("image/png");
   data = data.split(";", 2)[1];
   data = "data:image/png;headers=Content-Disposition%3A%20attachment%3B%20filename=" + filename + ";" + data;
   return data
}

var defaul_cn_options = {
  /* Default ChartNew.js options */
  animationSteps: 10,
  /* Adapt graph to change in layout */
  responsive: true,
  /* Let aspect ratio match the window dimensions */
  maintainAspectRatio: false,
  /* Re-scale font based on responsive relayout */
  responseScaleContent: true,
  /* Show legend describing each color */
  legend: true,
  /* Start animation immediately do not wait for the chart to be visible */
  dynamicDisplay: false,
  /* Mimimum interval between y-axis ticks */
  yAxisMinimumInterval: 10,
  /* Show label on bars/points */
  inGraphDataShow: true,
  /* Set legend text color to black */
  legendFontColor: "rgb(0,0,0,1)",
  /* Set axis text color to black */
  scaleFontColor: "rgb(0,0,0,1)",
  /* Round number to two decimals */
  roundNumber: -2,
  /* Display data title when mouse is over the chart */
  annotateDisplay : true, 
  /* Label do display on scale */
  scaleLabel: "<%=value%>",
  /* Set style for axis texts */
  scaleFontSize : 16,
  /* Set style of graph title */
  graphTitleFontFamily : "'Arial'",
  graphTitleFontSize : 24,
  graphTitleFontStyle : "bold",
  graphTitleFontColor : "#666",
  /* Set style of footnote text (only used in piecharts) */
  footNoteFontSize: 16,
  fmtXLabel: "ellipsize",
}

function draw_piechart(canvas, dimensions, measures, measure, data) {
  /* Draw piechart given a cavans element, a list of dimensions, a list of measure, the name of the
   * measure to represent and data rows containing in the same order the dimensions and measures
   * values */
  var datasets = [];
  var linedata = {datasets: datasets};
  linedata.labels = [""];
  var empty = []
  var n = dimensions.length;
  var option = $.extend({}, defaul_cn_options);
  var ctx = canvas.getContext("2d");
  var dimension_labels = [];
  for (var i = 0; i < dimensions.length; i++) {
    dimension_labels.push(dimensions[i].label);
  }

  for (var j = 0; j < measures.length; j++) {
    if (measures[j].name == measure) {
      break;
    }
  }
  if (j == measures.length) {
    // measure not found
    return;
  }
  option.graphTitle = wrap_text(
      capfirst(measures[j].label) + " par " + human_join(dimension_labels), 30)

  /* sort pie by slice size */
  data.sort(function (a, b) {
    return a.measures[j].value - b.measures[j].value;
  });

  /* Count number of empty cells */
  var n = data.length;
  var empty_count = 0;
  for (var i = 0; i < n; i++) {
     var value = data[i].measures[j].value;
     if (value > 1) {
         empty_count += 1;
     }
  }

  /* Build one dataset by measurement, it's the way the piecharts expects it. */
  var n = data.length;
  for (var i = 0; i < n; i++) {
     var value = data[i].measures[j].value;
     var title = [];

     for (var k = 0; k < data[i].coords.length; k++) {
       title.push(data[i].coords[k].value);
     }
     title = title.join();

     if (value > 1) {
       dataset = {
         data: [value],
         title: title,
         fillColor: spaced_hsla(datasets.length, empty_count, 100, 30, 0.5),
         strokeColor: spaced_hsla(datasets.length, empty_count, 100, 30, 0.75),
         highlightFill: spaced_hsla(datasets.length, empty_count, 100, 30, 0.75),
         highlightStroke: spaced_hsla(datasets.length, empty_count, 100, 30, 1)
       };
       datasets.push(dataset);
     } else {
        /* push empty pie slices to the empty array */
        empty.push(title);
     }
  }

  /* show only percentages */
  option.inGraphDataTmpl = "<%=v1+': '+v6+' %'%>";
  option.annotateLabel = "<%=v1+' pour '+v2+': '+v6+' %'%>";

  /* if some slices are empty or nearly empty, do not try to show them in the piechart but add a
   * footnore */
  if (empty.length) {
     option.footNote = wrap_text("Les valeurs pour " + human_join(empty)
       + " sont nulles ou presque.", 110);
  }
  new Chart(ctx).Pie(linedata, option);
}

function draw_barchart(canvas, dimensions, measures, measure, data) {
  /* Draw bar chart given a cavans element, a list of dimensions, a list of measure, the name of the
   * measure to represent and data rows containing in the same order the dimensions and measures
   * values */
  var dataset = {
    data: [],
    title: "",
    fillColor: [],
    strokeColor: [],
    highlightFill: [],
    highlightStroke: []
  }
  var datasets = [dataset];
  var linedata = {labels: [], datasets: datasets};
  var empty = []
  var n = dimensions.length;
  var option = $.extend({}, defaul_cn_options);
  var ctx = canvas.getContext("2d");
  var dimension_labels = [];
  for (var i = 0; i < dimensions.length; i++) {
    dimension_labels.push(dimensions[i].label);
  }

  for (var j = 0; j < measures.length; j++) {
    if (measures[j].name == measure) {
      break;
    }
  }
  if (j == measures.length) {
    // measure not found
    return;
  }
  measure = measures[j]

  dataset.title = measures[j].label;
  option.graphTitle = wrap_text(
      capfirst(measures[j].label) + " par " + human_join(dimension_labels), 30)

  dataset.fillColor = spaced_hsla(j, measures.length, 100, 30, 0.5);
  dataset.strokeColor = spaced_hsla(j, measures.length, 100, 30, 0.75);
  dataset.highlightFill = spaced_hsla(j, measures.length, 100, 30, 0.75);
  dataset.highlightStroke = spaced_hsla(j, measures.length, 100, 30, 1);

  var n = data.length;

  option.annotateLabel = "<%=wrap_text(v1+' pour <br/>'+ v2 + ': '+v3, 10)%>";
  option.inGraphDataTmpl = "<%=v3%>";

  if (measure.name == "count") {
    option.yAxisLabel = "quantité";
  }

  if (measure.name == "percent") {
    option.yAxisLabel = "pourcentage";
  }

  if (measure.type == "duration") {
    var max = 0;
    var scale = 0;

    for (var i = 0; i < n; i++) {
      var row = data[i];
      max = Math.max(row.measures[j].value, max);
      console.log("max", max)
    }
    console.log("max final", max)

    if (max > 1) {
      option.yAxisLabel = "jours";
      option.annotateLabel = "<%=v1+' pour ' + v2 + ': '+days_to_string(v3)%>";
      option.inGraphDataTmpl = "<%=days_to_string(v3)%>";
    } else if (max > (1. / 24)) {
      option.yAxisLabel = "heures";
      scale = 24;
      option.annotateLabel = "<%=v1+' pour ' + v2 + ': '+days_to_string(v3 / 24.)%>";
      option.inGraphDataTmpl = "<%=days_to_string(v3 / 24.)%>";
    } else {
      option.yAxisLabel = "minutes";
      scale = 24 * 60;
      option.annotateLabel = "<%=v1+' pour ' + v2 + ': '+days_to_string(v3 / (60 * 24))%>";
      option.inGraphDataTmpl = "<%=days_to_string(v3 / (60 * 24))%>";
    }
    if (scale > 0) {
      for (var i = 0; i < n; i++) {
        var row = data[i];
        row.measures[j].value *= scale;
      }
    }
  }

  for (var i = 0; i < n; i++) {
    var row = data[i];
    var title = [];

    for (var k = 0; k < data[i].coords.length; k++) {
      title.push(data[i].coords[k].value);
    }
    title = title.join();
    linedata.labels.push(title)

    dataset.data.push(row.measures[j].value);
  }

  $.extend(option, {
      //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
      scaleBeginAtZero : true,

      //Boolean - Whether grid lines are shown across the chart
      scaleShowGridLines : true,

      //String - Colour of the grid lines
      scaleGridLineColor : "rgba(0,0,0,.05)",

      //Number - Width of the grid lines
      scaleGridLineWidth : 1,

      //Boolean - Whether to show horizontal lines (except X axis)
      scaleShowHorizontalLines: true,

      //Boolean - Whether to show vertical lines (except Y axis)
      scaleShowVerticalLines: true,

      //Boolean - If there is a stroke on each bar
      // barShowStroke : true,

      //Number - Pixel width of the bar stroke
      barStrokeWidth : 2,

      //Number - Spacing between each of the X value sets
      barValueSpacing : 5,

      //Number - Spacing between data sets within X values
      barDatasetSpacing : 1,
  });
  new Chart(ctx).Bar(linedata, option);
}

/* jQuery event handlers and widget setup */
$(function () {
  /* Setup datepicker on input fields */
  if ($.datepicker) {
    $('input[type=date]').datepicker({
      dateFormat: 'yy-mm-dd',
      changeMonth: true,
      changeYear: true,
    },
    $.datepicker.regional['fr']);
  }

  /* Submit after 300ms on any change to form input */
  $('input, select').on('change', function () {
    setTimeout(function () {
      $('form').ajaxSubmit({success: function (data) {
        var $content = $(data);
        $('#data').replaceWith($content.find('#data'));
        $('#breadcrumb').replaceWith($content.find('#breadcrumb'));
        location.hash = 'data';
      }});
    }, 300);
    return true;
  });

  /* Add clear button to date fields */
  $('input[type=date]').addClear();
})
