// Copyright Manu Cornet 2009. All rights reserved.

var drawcurve = function() {};

drawcurve.NUMBER_OF_QUARTIERS_PER_ARR = 4;
drawcurve.AVERAGE_NOTICE_CHAR = 'M';
drawcurve.MISSING_DATA_NOTICE_CHAR = '.';
drawcurve.VALUE_FOR_MISSING_DATA = '-1';
drawcurve.SCALE_Y = 20;

var trimestres;
var arrs;
var maxPrice;
var plots = [];
var filledByAverage = [];

var quartiersNames = [
  [], // 0th arrondissement
  [['Place Vendôme'], ['Palais Royal'], ['Les Halles'],
      ['St Germain l\'Auxerrois']], // 1
  [['Gaillon'], ['Vivienne'], ['Mail'], ['Bonne Nouvelle']], // 2
  [['Arts et métiers'], ['Enfants Rouges'], ['Sainte Avoye'],
      ['Archives']], // 3
  [['St Merri'], ['St Gervais'], ['Arsenal'], ['Notre-Dame']], // 4
  [['Sorbonne'], ['St Victor'], ['Val de Grâce'],
      ['Jardin des Plantes']], // 5
  [['St Germain des Prés'], ['Monnaie'], ['ND des Champs'], 
      ['Odéon']], // 6
  [['Gros Caillou'], ['Les Invalides'], ['St Thomas d\'Aquin'], 
      ['École Militaire']], // 7
  [['Europe'], ['Faubourg du Roule'], ['La Madeleine'], 
      ['Champs Élysée']], // 8
  [['St Georges'], ['Rochechouart'], ['Chaussée d\'Antin'],
      ['Faubourg Montmartre']], // 9
  [['St Vincent de Paul'], ['Hôpital St Louis'], ['Porte Saint-Denis'],
     ['Porte St Martin']], // 10
  [['Folie Méricourt'], ['St Ambroise'], ['La Roquette'],
      ['Ste Marguerite']], // 11
  [['Quinze Vingts'], ['Picpus'], ['Bel Air'], ['Bercy']], // 12
  [['Croulebarbe'], ['Salpétrière'], ['Maison Blanche'], ['Gare']], // 13
  [['Montparnasse'], ['Plaisance'], ['Petit Montrouge'],
      ['Parc Montsouris']], // 14
  [['Grenelle'], ['Necker'], ['Javel'], ['St Lambert']], // 15
  [['Pte Dauphine'], ['Chaillot'], ['La Muette'], ['Auteuil']], // 16
  [['Épinettes'], ['Batignolles'], ['Plaine Monceau'], ['Ternes']], // 17
  [['Grandes Carrières'], ['Clignancourt'], ['La Goutte d\'Or'],
      ['La Chapelle']], // 18
  [['Pont de Flandre'], ['La Villette'], ['Combat'], ['Amérique']], // 19
  [['Belleville'], ['St Fargeau'], ['Père Lachaise'],
      ['Charonne']], // 20
];

drawcurve.prototype.getData = function(arrondissement) {
  // Validate the input.
  arrondissement = '' + arrondissement;
  if (arrondissement.length == 0) {
    // Can't do anything without yoouuuuu-ouhouuu.
    return;
  }
  if (arrondissement.length == 1) {
    arrondissement = '0' + arrondissement;
  }
  $.get("price_request.php", {'a': arrondissement}, drawcurve.onDataReceived);
};


drawcurve.onDataReceived = function(data) {
  arrs = [];
  var dataValues = [];
  maxPrice = 0;
  var currentValue;
  var data = drawcurve.processData(data);
  trimestres = trimestres.reverse();

  // We have all the data in arrays, now we need to format it.
  for (h = 0; h < arrs.length; h++) {
    // Initialize for this arrondisement.
    dataValues[arrs[h]] = [];
    for (var j = 0; j < drawcurve.NUMBER_OF_QUARTIERS_PER_ARR; j++) {
      // Initialize for this quartier.
      dataValues[arrs[h]][j] = [];
      for (i = 0; i < trimestres.length; i++) {
        currentValue = data[arrs[h]][trimestres[i]][j];
        var intCurrentValue = parseInt(currentValue);
        if (intCurrentValue > maxPrice) {
          maxPrice = intCurrentValue;
        }
        dataValues[arrs[h]][j].push(currentValue);
      }
    }
  }
  drawcurve.initializeCurves(dataValues);
  drawcurve.makeCheckboxes(plots);
  drawcurve.showCurvesAccordingToChoices();
};

drawcurve.processData = function(rawData) {
  var data = [];
  trimestres = [];
  var trimestresIsComplete = false;
  var arr;
  var arrRegExp = new RegExp(/^=A\d\d/);
  var lines = rawData.split('\n');

  // For each line of the data input
  for (var i = 0; i < lines.length; i++) {
    // Trim the line.
    lines[i] = lines[i].replace(/^\s+|\s+$/g, '');
    // Continue if we have an empty line.
    if (!lines[i].length) {
      continue;
    }

    // If this is a line saying we start a new arrondissement
    if (arrRegExp.test(lines[i])) {
      arr = lines[i].match(arrRegExp)[0].replace(/=A/, '');
      arrs.push(arr);
      data[arr] = [];
      filledByAverage[arr] = [];
      if (trimestres.length != 0) {
        trimestresIsComplete = true;
      }
      continue;
    }

    // We use tab-separated values.
    var fields = lines[i].split('\t');
    // Trim everything.
    for (var j = 0; j < fields.length; j++) {
      fields[j] = fields[j].replace(/^\s+|\s+$/g, '');
    }

    // The trimestre is the first bit of data.
    var trimestre = fields[0];
    if (!trimestresIsComplete) {
      trimestres.push(trimestre);
    }
    data[arr][trimestre] = [];
    filledByAverage[arr][trimestre] = [];
    if (fields[1] == drawcurve.AVERAGE_NOTICE_CHAR) {
      filledByAverage[arr][trimestre] = true;
      var average = fields[2];
      drawcurve.fillAverage(data[arr], trimestre, average);
    } else {
      filledByAverage[arr][trimestre] = false;
      for (var j = 1; j < fields.length; j++) {
        data[arr][trimestre][j - 1] = fields[j];
        if (fields[j] == drawcurve.MISSING_DATA_NOTICE_CHAR) {
          data[arr][trimestre][j - 1] = drawcurve.VALUE_FOR_MISSING_DATA;
        }
      }
    }
  }
  return data;
};

drawcurve.initializeCurves = function(dataValues) {
  document.getElementById('chart').innerHTML = '';

  var currentValue;
  var curveNumber = 0;
  var currentTrimestre;
  var adjustedCurveNumbers = [];

  for (i = 0; i < arrs.length; i++) {

    for (var j = 0; j < drawcurve.NUMBER_OF_QUARTIERS_PER_ARR; j++) {
      plots[curveNumber] = {};
      plots[curveNumber].data = [];
      var arrAsInt = parseInt(arrs[i]);
      if (quartiersNames && quartiersNames[arrAsInt] && quartiersNames[arrAsInt][j]) {
        plots[curveNumber].label = arrs[i] + ' ' + quartiersNames[arrAsInt][j];
      }
      for (var k = 0; k < dataValues[arrs[i]][j].length; k++) {
        currentTrimestre = trimestres[k];
        plots[curveNumber].data[k] = [];
        currentValue = parseInt(dataValues[arrs[i]][j][k]);
        if (currentValue == -1) {
          plots[curveNumber].data[k] = null;
        } else {
          plots[curveNumber].data[k][0] = drawcurve.trimestreToUnix(currentTrimestre);
          plots[curveNumber].data[k][1] = currentValue;
        }
      }      
      curveNumber++;
    }

    // Also make the average curve.
    plots[curveNumber] = {};
    plots[curveNumber].data = [];
    var arrAsInt = parseInt(arrs[i]);
    plots[curveNumber].label = arrs[i] + ' (Moy)';
    // Loop over all quartiers of this arrondissement.
    for (var j = 0; j < drawcurve.NUMBER_OF_QUARTIERS_PER_ARR; j++) {

      // And loop over all time values for this quartier.
      for (var k = 0; k < dataValues[arrs[i]][j].length; k++) {

        currentTrimestre = trimestres[k];
        plots[curveNumber].data[k] = [];
        plots[curveNumber].data[k][0] = drawcurve.trimestreToUnix(currentTrimestre);

        // Compute the average.
        var averageEls = [];
        for (var e = 1; e < 5; e++) {
          if (plots[curveNumber - e].data[k]) {
            averageEls.push(plots[curveNumber - e].data[k][1]);
          }
        }
        if (averageEls.length == 0) {
          plots[curveNumber].data[k] = null;
        } else {
          var average = 0;
          for (var e = 0; e < averageEls.length; e++) {
            average += averageEls[e];
          }
          average = average / (averageEls.length);
          plots[curveNumber].data[k][1] = average;
        }

        // Also delete nodes if they were "assumed" by average
        if (filledByAverage[arrs[i]][currentTrimestre]) {
          adjustedCurveNumbers.push('' + curveNumber + ' ' + arrs[i] + ' ' + currentTrimestre + ' ' +k);
          // TODO: ???
          // plots[curveNumber - 1].data[k] = null;
          plots[curveNumber - 2].data[k] = null;
          plots[curveNumber - 3].data[k] = null;
          plots[curveNumber - 4].data[k] = null;
        }
      }
    }
    curveNumber++;
  }
};


drawcurve.fillAverage = function(arrData, trimestre, average) {
  if (average == drawcurve.MISSING_DATA_NOTICE_CHAR) {
    average = '-1';
  }
  for (var i = 0; i < drawcurve.NUMBER_OF_QUARTIERS_PER_ARR; i++) {
    arrData[trimestre][i] = average;
  }
};


drawcurve.makeCheckboxes = function(plots) {
  var choiceContainer = $("#checkboxes");
  var commands = $('<div class="commands"></div>');
  var toutCocherLink = $('<span class="command">Tout Cocher</span>');
  var toutDecocherLink = $('<span class="command">Tout décocher</span>');
  commands.append(toutCocherLink);
  commands.append(toutDecocherLink);
  choiceContainer.append(commands);
  choiceContainer.append('<br />');
  toutCocherLink.click(drawcurve.checkAll);
  toutDecocherLink.click(drawcurve.uncheckAll);

  for (var arrondissement = 1; arrondissement < quartiersNames.length; arrondissement++) {
    var arrContainer = $('<div class="arrline"></div>');
    arrContainer.append('<input type="checkbox" name="' + 
                         arrondissement + '.5' + '"' +
                         ((arrondissement < 6) ? ' checked="checked"' : '') +
                         '><h2>' +
                         arrondissement + '</h2></input>');
    for (var quartier = 0; quartier < quartiersNames[arrondissement].length; quartier++) {
      arrContainer.append('<div><input type="checkbox" name="' +
                             arrondissement + '.' + (quartier + 1) +
                           '" />' +
                             quartiersNames[arrondissement][quartier] + '</input></div>');
    }
    choiceContainer.append(arrContainer);
  }
  choiceContainer.find("input").click(drawcurve.showCurvesAccordingToChoices);
};

drawcurve.showCurvesAccordingToChoices = function() {
  var dataToPlot = [];

  $("#checkboxes").find("input:checked").each(function () {
    var name = $(this).attr("name");
    var elems = name.split('.');
    var arr = parseInt(elems[0]);
    var quartier = parseInt(elems[1]);
    var index = (drawcurve.NUMBER_OF_QUARTIERS_PER_ARR + 1) * (arr - 1) + (quartier - 1);
    if (arr && quartier && plots[index]) {
      dataToPlot.push(plots[index]);
    }
  });

    $.plot($('#chart'), dataToPlot, {
      xaxis: {mode: 'time'},
      yaxis: { min: 1500 },
      lines: {show: true},
      points: {show: true},
      selection: {mode: 'xy'},
      grid: { hoverable: true, clickable: true },
      legend: {
        position: 'nw',
        container: $('#legendinner')}
    });
    this.listenHover();
};

drawcurve.checkAll = function() {
 $("#checkboxes").find("input").each(function () {
    $(this).attr("checked", true);
  });
  drawcurve.showCurvesAccordingToChoices();
};

drawcurve.uncheckAll = function() {
 $("#checkboxes").find("input:checked").each(function () {
    $(this).attr("checked", false);
  });
  drawcurve.showCurvesAccordingToChoices();
};

drawcurve.showTooltip = function(x, y, contents) {
};

drawcurve.listenHover = function() {
  var previousPoint = null;
  $("#chart").bind("plothover", function (event, pos, item) {
    $("#x").text(pos.x.toFixed(2));
    $("#y").text(pos.y.toFixed(2));

    if (item) {
      if (previousPoint != item.datapoint) {
        previousPoint = item.datapoint;

        $("#tooltip").remove();
        var x = item.datapoint[0].toFixed(2),
        y = item.datapoint[1].toFixed(0);

        var contents = y + ' € pour ' + item.series.label + ' au ' +
                       drawcurve.unixToTrimestre(x);
        $('<div id="tooltip">' + contents + '</div>').css( {
          position: 'absolute',
          display: 'none',
          top: item.pageY + 5,
          left: item.pageX + 5,
          border: '1px solid #fdd',
          padding: '2px',
          'background-color': '#fee',
          opacity: 0.80
        }).appendTo("body").fadeIn(200);
        // this.showTooltip(item.pageX, item.pageY,
        // item.series.label + " of " + x + " = " + y);
      }
    } else {
      $("#tooltip").remove();
      previousPoint = null;            
    }
  });
}

drawcurve.trimestreToUnix = function(trimestre) {
  var year = parseInt(trimestre.substr(3, 4));
  var month = parseInt(trimestre.substr(1, 1)) * 3 - 2;
  var date = new Date();
  date.setFullYear(year, month - 1, 1);
  return date.getTime();
}

drawcurve.unixToTrimestre = function(unix) {
  var date = new Date();
  date.setTime(unix);
  var ieme = (date.getMonth() / 3 + 1 == 1) ? 'er' : 'e';
  return '' + (date.getMonth() / 3 + 1) + ieme + ' trim ' + date.getFullYear();
}
