/*
User Story: FA18| VIP-172, mvale080 (Fuzzy Matching)
    This function compares two strings using the jaro winkler string comparison algorithm.
    The function will return a value between 0 and 1, with 0 being absolutely no matching and 1 being a perfect match. Any value between that shows the degree of match.
    A higher number will mean a closer match so adjust the function accordingly. Reccommended values to use are between 0.85 and 0.90.
*/
(function () {
  angular.module('vip-projects')
    .factory('jaro_winklerService', function () {
      var jaro_winkler = {};

      jaro_winkler.distance = function (s1, s2) {
        var m = 0;

        // Exit early if either are empty.
        if (s1.length === 0 || s2.length === 0) {
          return 0;
        }

        // Exit early if they're an exact match.
        if (s1 === s2) {
          return 1;
        }
        s1 = s1.trim().toUpperCase();
        s2 = s2.trim().toUpperCase();

        var range = (Math.floor(Math.max(s1.length, s2.length) / 2)) - 1,
          s1Matches = new Array(s1.length),
          s2Matches = new Array(s2.length);

        for (i = 0; i < s1.length; i++) {
          var low = (i >= range) ? i - range : 0,
            high = (i + range <= s2.length) ? (i + range) : (s2.length - 1);

          for (j = low; j <= high; j++) {
            if (s1Matches[i] !== true && s2Matches[j] !== true && s1[i] === s2[j]) {
              ++m;
              s1Matches[i] = s2Matches[j] = true;
              break;
            }
          }
        }

        // Exit early if no matches were found.
        if (m === 0) {
          return 0;
        }

        // Count the transpositions.
        var k = n_trans = 0;

        for (i = 0; i < s1.length; i++) {
          if (s1Matches[i] === true) {
            for (j = k; j < s2.length; j++) {
              if (s2Matches[j] === true) {
                k = j + 1;
                break;
              }
            }

            if (s1[i] !== s2[j]) {
              ++n_trans;
            }
          }
        }

        var weight = (m / s1.length + m / s2.length + (m - (n_trans / 2)) / m) / 3,
          l = 0,
          p = 0.1;

        if (weight > 0.7) {
          while (s1[l] === s2[l] && l < 4) {
            ++l;
          }

          weight = weight + l * p * (1 - weight);
        }

        return weight;
      };
      return jaro_winkler;
    });
}());

