/**
 * Calculate the distances by using the numbers, strings and dates.
 * @param  {node} source
 * @param  {node} target
 * @param  {array} properties - the properties of the nodes.
 * @param  {object} normArgs   - the normalization arguments.
 * @return {number}            the distance between source and target nodes.
 */
function calculateDistance(source, target, properties, normArgs) {
  var val1 = 0.0, val2 = 0.0,
      sumDiff = 0.0,
      ordDiff = 1.0,
      ORD_FACTOR = 0.75,
      cols = 0,
      average = normArgs.avg,
      sigma = normArgs.sig,
      st_dev = normArgs.st_d;

  // Iterate through every column of data
  for (var i = 0; i < properties.length; i++) {
    property = properties[i];
    if (source.hasOwnProperty(property) && target.hasOwnProperty(property)
        && property.toLowerCase() !== "index" && property.toLowerCase() !== "type") {
      var s = source[property],
          t = target[property];

      // Comparing Floats and Integers
      if ((isNumeric(s) && isNumeric(t))) {
        val1 = parseFloat(s);
        val2 = parseFloat(t);
        if (sigma[i] != 0) {
          val1 = (val1 - average[i]) / (st_dev[i] * sigma[i]);
          val2 = (val2 - average[i]) / (st_dev[i] * sigma[i]);
        }
        sumDiff += (val1-val2) * (val1-val2);
        cols++;
      // Comparing strings
      } else if (/[a-zA-Z]/.test(s) && /[a-zA-Z]/.test(t) && s === t) {
        ordDiff *= ORD_FACTOR;
        cols++;
      } else {
        // Comparing Dates
        var parsedDateS = Date.parse(s);
        var parsedDateT = Date.parse(t);
        if (isNaN(s) && !isNaN(parsedDateS)
            && isNaN(t) && !isNaN(parsedDateT)) {

          val1 = parsedDateS.valueOf(),
          val2 = parsedDateT.valueOf();

          if (sigma[i] !== 0) {
            val1 = (val1 - average[i]) / (st_dev[i] * sigma[i]);
            val2 = (val2 - average[i]) / (st_dev[i] * sigma[i]);
          }
          sumDiff += (val1-val2) * (val1-val2);
          cols++;
        }
      }
    }
  }
  sumDiff = Math.sqrt(sumDiff);
  sumDiff *= ordDiff;

  if (cols > 0) {
    sumDiff *= properties.length/cols;
  }

  //console.log(sumDiff);
  return sumDiff;
}
