Event.observe(window, 'load', function() {
 assignColor();
 if($('auth_password1')) {
   $('auth_password1').observe('change', CheckPasswordSecurity);
   $('auth_password1').observe('keyup', CheckPasswordSecurity);

   if($('auth_password2')) {
     $('auth_password2').observe('keyup', CheckPasswordSecurity);
     $('auth_password2').observe('change', CheckPasswordSecurity);
   }

   setTimeout(CheckPasswordSecurity, 700);
 }
});

// {{{ CheckPasswordSecurity()
function CheckPasswordSecurity(){
  if(!$('auth_password1'))
    return;

  var v = $F('auth_password1');

  mark_password_as('bad', 'all');

  if(!longer_than_5(v))
    return DrawPasswordSecurity(0);

  if(!shorter_than_20(v))
    return DrawPasswordSecurity(0);

  // So far so good, the rest are bonuses:
  var score = 1;

  has_username(v) && score++

  password_confirmed();

  has_username(v) && score++;

  has_mixed_letters_and_numbers(v) && score++;

  // If it has punctuation too that's even better:
  has_punctuation(v) && score++;

  // Bad if they're sequential
  if(!FindSequence(v)) {
    mark_password_as('good', 'non_sequential');
    score++;
  }

  // Or if it contains a dictionary word
  // if(!FindDictionaryWord(v)) score++;

  DrawPasswordSecurity(score);
  return score;
} // }}}

// {{{ longer_than_5(val)
function longer_than_5(v) {
  if(v.length < 5) return 0;

  mark_password_as('good', 'longer_than_5');
  return 1;
} // }}}

// {{{ shorter_than_20(val)
function shorter_than_20(v) {
  if(v.length > 20) return 0;

  mark_password_as('good', 'shorter_than_20');
  return 1;
} // }}}

// {{{ password_confirmed()
function password_confirmed() {
  if($('auth_password1')
     && $('auth_password2')
     && $F('auth_password1')
     && $F('auth_password1') == $F('auth_password2')) {
    mark_password_as('good', 'password_confirmed');
    return 1;
  }

  mark_password_as('bad', 'password_confirmed');
  return 0;
} // }}}

// {{{ has_mixed_letters_and_numbers(v)
function has_mixed_letters_and_numbers(v) {
  // Returns 0 on only letters or only numbers:
  if(v.match(/^[a-z]+$/i) || v.match(/^[0-9]+$/)) {
    return 0;
  }
  mark_password_as('good', 'letters_and_numbers');
  return 1;
} // }}}

// {{{ has_punctuation(v)
function has_punctuation(v) {
  if(v.match(/[^a-z0-9]/i)) {
    mark_password_as('good', 'has_punctuation');
    return 1;
  }

  return 0;
} // }}}

// {{{ has_username(v)
function has_username(v) {
  mark_password_as('bad', 'has_username');

  var uname = $('auth_user_name')
              ? $F('auth_user_name')
              : $('current_username')
                ? $('current_username').innerHTML : 0;

  if(!uname || !v.match(new RegExp(uname))) {
    mark_password_as('good', 'has_username');
    return 1;
  }

  return 0;
} // }}}

// {{{ FindSequence(v)
function FindSequence(v){
  if(v.indexOf('asdf') != -1) return 1;
  if(v.indexOf('qwerty') != -1) return 1;
  if(v.match(/(.)\1{2}/)) return 1;

  var arr = new Array(v.length);
  var i;
  for(i = 0; i < v.length; i++){
    arr[i] = v.charCodeAt(i);
  }

  for(i = 0; i < v.length-2; i++){
    // Ascending values:
    if(arr[i]+1 == arr[i+1] && arr[i]+2 == arr[i+2]) return 1;
    // Descending values:
    if(arr[i]-1 == arr[i+1] && arr[i]-2 == arr[i+2]) return 1;

    // # {{{ If numbers
    if(arr[i]   > 49 && arr[i]   < 57 &&
       arr[i]+1 > 49 && arr[i]+1 < 57 &&
       arr[i]+2 > 49 && arr[i]+2 < 57){
      // Ascending numeric values in steps of 2
      if(arr[i]+2 == arr[i+1] && arr[i]+4 == arr[i+2]) return 1;

      // Descending numeric values in steps of 2
      if(arr[i]-2 == arr[i+1] && arr[i]-4 == arr[i+2]) return 1;

      // Ascending numeric values in steps of 3
      if(arr[i]+3 == arr[i+1] && arr[i]+6 == arr[i+2]) return 1;

      // Descending numeric values in steps of 3
      if(arr[i]-3 == arr[i+1] && arr[i]-6 == arr[i+2]) return 1;
    } // # }}}
  }

  return 0;
} // }}}

// {{{ DrawPasswordSecurity(val)
function DrawPasswordSecurity(val){
  var psicont = $('psicont');
  psicont.select('.psi').each(function(el) {
    var match = el.id.match(/^psi([0-9]+)$/);

    if(!match)
      return 0;

    var num = match[1];
    if(num < val) {
      if(el.hasClassName('psibad'))
        el.removeClassName('psibad');
    } else {
      el.addClassName('psibad');
    }
  });

  $R(0, val).each(function(v) {
    psicont.addClassName('psi'+v);
  });

  return 0;
} // }}}

// {{{ FindDictionaryWord(v)
function FindDictionaryWord(v){
  return 0;

  // Put AJAX code in here :)
  mark_password_as('bad', 'not_dictionary');

  if(found_in_dictionary)
    return 1;

  mark_password_as('good', 'not_dictionary');
  return 0;
} // }}}

// {{{ mark_password_as(type, id)
function mark_password_as(type, id) {
  if(id == 'all') {
    if($('pstests')) {
      $('pstests').select('li').each(function(li) {
        mark_password_as(type, li.id.replace(/^pst_/, ''));
      });
      return;
    }
  }

  var el = $('pst_' + id);
  if(!el) return;


  if(type == 'bad') {
    el.addClassName('bad');
  } else {
    el.removeClassName('bad');
  }
} // }}}

// {{{ assignColor()
function assignColor() {
  var colours = [ '#fb0300' ];
  var psis = $$('#psicont .psi');

  if(psis.length == 8) {
    colours = [ '#fb0300', '#f54802', '#f08e05', '#ebd508', '#c7eb09',  '#86d309', '#44bc08', '#03a508' ];
  } else if(psis.length == 7) {
    colours = [ '#fb0300', '#f55403', '#eea606', '#76ce09', '#9cdb09', '#4fc008', '#03a508' ];
  } else if(psis.length == 6) {
    colours = [ '#fb0300', '#f3650f', '#ecc608', '#bae709', '#5ec508', '#03a508' ];
  } else if(psis.length == 5) {
    colours = [ '#fb0300', '#f27d05', '#e9f80a', '#76ce09', '#03a508' ];
  } else if(psis.length == 4) {
    colours = [ '#fb0300', '#eea606', '#9cdb09', '#03a508' ];
  } else if(psis.length == 3) {
    colours = [ '#fb0300', '#e9f80a', '#03a508' ];
  } else if(psis.length == 2) {
    colours = [ '#fb0300', '#03a508' ];
  }

  psis.each(function(el) {
    el.addClassName('psibad');
    el.setStyle({ backgroundColor : colours.shift() });
  });
} // }}}
