var SUPERREG = {
  // version 2
  form_el: null,
  form_id: null,
  ajax_queue: null,
  
  init: function() {
    
    this.form_fields = new Array();
    this.ajax_queue = new Array();
    var nbsp = '&nbsp;';
    
    // reenable submit button when using back button
    $$('#saveForm').each(function(elem) {
      elem.disabled = false;
    });

    // setup each form field object like this:
    // id, eventName, checkMethod, successText, failText
    
    if( $('mobilenumber_form') ) {
      this.form_id = 'mobilenumber_form';
      this.form_el = $(this.form_id);
      // form fields for sms_code_page
      this.form_fields = {
        'user_sms_code': new SuperField( 'user_sms_code', 'change', this.validateAjax, nbsp ),
        'user_calling_code': new SuperField( 'user_calling_code', 'change', this.validateCallingCode, nbsp ),
        'user_mobilenumber': new SuperField( 'user_mobilenumber', 'change', this.validateMobilenumber, nbsp )
      };
    } 
    if( $("user_form") ){
      this.form_id = 'user_form';
      this.form_el = $(this.form_id);
      // form fields for new
      this.form_fields = {
        'user_login': new SuperField( 'user_login', 'change', this.validateAjax, nbsp ),
        'user_calling_code': new SuperField( 'user_calling_code', 'change', this.validateCallingCode, nbsp ),
        'user_mobilenumber': new SuperField( 'user_mobilenumber', 'change', this.validateMobilenumber, nbsp ),
        'user_email': new SuperField( 'user_email', 'change', this.validateAjax, nbsp ),
        'user_password': new SuperField( 'user_password', 'change', this.validatePassword, 'Ugyldig passord.' ),
        'user_password_confirmation': new SuperField( 'user_password_confirmation', 'change', this.validatePasswordConfirm, 'Passordene samsvarer ikke.' ),
        'user_terms_of_service': new SuperField( 'user_terms_of_service', 'click', this.validateCheckbox, nbsp )
      };
    }
    for(var key in this.form_fields) {
      var obj = this.form_fields[key];
      if(obj.element.value != '' && obj.id != 'user_calling_code' && obj.id != 'user_terms_of_service') {
        obj.checkValue();
      };
    };
  },
  validateCheckbox: function(value) {
    if( this.element.checked ) {
      return true;
    } else {
      return false;
    }
  },
  sendAjaxRequest: function(requestURL) {
    return new Ajax.Request(requestURL, {
      method: 'get',
      onSuccess: function(transport) {
        var response_object = transport.responseText.evalJSON();
        var queue_id = response_object[0][1];
        var field_object = SUPERREG.form_fields[queue_id];
        if(response_object[1] != undefined) {
          error_text = response_object[1][1];
          field_object.markError(error_text);
        } else {
          field_object.markSuccess('&nbsp;');
        }
      }
    });
  },
  validateCallingCode: function(value) {
    if( $('user_mobilenumber').value.toString() != '' ) {
      SUPERREG.form_fields.user_mobilenumber.checkValue();
    };
    return 'null';
  },
  validateMobilenumber: function(value) {
    this.markChecking('&nbsp;');
    var requestURL = "/user_registration/ajax_check_field?";
    requestURL += 'calling_code=' + encodeURIComponent( $('user_calling_code').value.toString() );
    requestURL += '&mobilenumber=' + encodeURIComponent( this.element.value.toString() );
    var user_id = this.element.getAttribute("data-user-id");
    if(user_id) {
      requestURL += "&user_id=" + user_id;
    };
    requestURL += "&queue_id=" + this.id;
    this.ajax_request = SUPERREG.sendAjaxRequest(requestURL);
    return 'ajax';
  },
  validateAjax: function(value) {
    this.markChecking('&nbsp;');
    var requestURL = "/user_registration/ajax_check_field?";
    requestURL += this.key + "=" + encodeURIComponent(value);
    var user_id = this.element.getAttribute("data-user-id");
    if(user_id) {
      requestURL += "&user_id=" + user_id;
    };
    requestURL += "&queue_id=" + this.id;
    this.ajax_request = SUPERREG.sendAjaxRequest(requestURL);
    return 'ajax';
  },
  validatePassword: function(value) {
    // check confirmation if necessary
    var confirm_field = SUPERREG.form_fields['user_password_confirmation'];
    var confirm_value = confirm_field.element.value.toString();
    if( confirm_value != '' ) {
      confirm_field.checkValue(); 
    }
    // check password value for correct character range
    if(value.length >= 6 && value.length <= 15) {
      return true;
    } else {
      return false;
    }   
  },
  validatePasswordConfirm: function(value) {
    // check password confirm for match of password field value
    if(value == $('user_password').value) { 
      return true; 
    } else {
      return false;
    }
  }
};

// SuperField class - generic class for each field
// Each field will have a SuperField object associated which
// will hold all data and methods related to this field
// depends on prototype.js object creation
var SuperField = Class.create({
  initialize: function(id,eventName,checkMethod,failText) {
    this.id = id;
    this.key = id.replace('user_','');
    this.element = $(id);
    this.eventName = eventName;
    this.successText = '&nbsp;';
    this.failText = failText;
    this.checkMethod = checkMethod;
    this.status_el = this.element.up().up().select('.input_status')[0];
    this.setupField();
  },
  setupField: function() {
    // setup the event
    this.element.observe( this.eventName, this.fieldChangeHandler.bindAsEventListener(this) );
    // special cases
    if( this.id=="user_login" && this.element.value=="" ) {
      this.markFocused();
    }
  },
  fieldChangeHandler: function(event) {
    this.checkValue();
  },
  checkValue: function() {
    var value = this.element.value;
    if( value !== '') {
      var valid = this.checkMethod(value);
      if(valid === true) {
        this.markSuccess(this.successText);
      } else if(valid === false){
        this.markError(this.failText);
      } else if(valid === 'ajax') {
        this.markChecking('&nbsp;');
      } else if(valid === 'null') {
        // do nothing
      }
    }
  },
  resetMark: function() {
    this.status_el.removeClassName('fail');
    this.status_el.removeClassName('neutral');
    this.status_el.removeClassName('success');
    this.status_el.removeClassName('checking');
  },
  markFocused: function() {
    this.element.focus();
    this.element.up().up().addClassName('focused');
  },
  markChecking: function(text) {
    this.status_el.innerHTML = text;
    this.resetMark();
    this.status_el.addClassName('checking');
  },
  markError: function(text) {
    this.status_el.innerHTML = text;
    this.resetMark();
    this.status_el.addClassName('fail');
  },
  markSuccess: function(text) {
    this.status_el.innerHTML = text;
    this.resetMark();
    this.status_el.addClassName('success');
  },
  markNeutral: function(text) {
    this.status_el.innerHTML = text;
    this.resetMark();
    this.status_el.addClassName('neutral');
  },
  getValue: function() {
    return this.element.value;
  }
});

SUPERREG.CountryCheck = {
  form_el: null,
  element: null,
  script: null,
  countryCode: 'no',
  countryName: 'Norway',
  callingCode: '47',
  geoipCountryCode: null,
  geoipCountryName: null,
  geoipCallingCode: null,
  countries: [
    { 'name': 'norway', 'country_code': 'no', 'calling_code': '47', 'digits': '8' },
    { 'name': 'sweden', 'country_code': 'se', 'calling_code': '46', 'digits': '9' },
    { 'name': 'denmark', 'country_code': 'dk', 'calling_code': '45', 'digits': '8' },
    { 'name': 'greece', 'country_code': 'gr', 'calling_code': '30', 'digits': '9' },
    { 'name': 'netherlands', 'country_code': 'nl', 'calling_code': '31', 'digits': '9' },
    { 'name': 'belgium', 'country_code': 'be', 'calling_code': '32', 'digits': '8' },
    { 'name': 'france', 'country_code': 'fr', 'calling_code': '33', 'digits': '9' },
    { 'name': 'spain', 'country_code': 'es', 'calling_code': '34', 'digits': '9' },
    { 'name': 'portugal', 'country_code': 'pt', 'calling_code': '351', 'digits': '9' },
    { 'name': 'luxembourg', 'country_code': 'lu', 'calling_code': '352', 'digits': '8' },
    { 'name': 'ireland', 'country_code': 'ie', 'calling_code': '353', 'digits': '9' },
    { 'name': 'malta', 'country_code': 'mt', 'calling_code': '356', 'digits': '8' },
    { 'name': 'cypress', 'country_code': 'cy', 'calling_code': '357', 'digits': '8' },
    { 'name': 'finland', 'country_code': 'fi', 'calling_code': '358', 'digits': '9' },
    { 'name': 'bulgaria', 'country_code': 'bg', 'calling_code': '359', 'digits': '8' },
    { 'name': 'hungaria', 'country_code': 'hu', 'calling_code': '36', 'digits': '8' },
    { 'name': 'lithuania', 'country_code': 'lt', 'calling_code': '370', 'digits': '8' },
    { 'name': 'latvia', 'country_code': 'lv', 'calling_code': '371', 'digits': '8' },
    { 'name': 'estonia', 'country_code': 'ee', 'calling_code': '372', 'digits': '7' },
    { 'name': 'croatia', 'country_code': 'hr', 'calling_code': '385', 'digits': '8' },
    { 'name': 'slovenia', 'country_code': 'si', 'calling_code': '386', 'digits': '8' },
    { 'name': 'italy', 'country_code': 'it', 'calling_code': '39', 'digits': '9' },
    { 'name': 'romania', 'country_code': 'ro', 'calling_code': '40', 'digits': '9' },
    { 'name': 'switzerland', 'country_code': 'ch', 'calling_code': '41', 'digits': '9' },
    { 'name': 'czech republic', 'country_code': 'cz', 'calling_code': '420', 'digits': '9' },
    { 'name': 'slovakia', 'country_code': 'sk', 'calling_code': '421', 'digits': '9' },
    { 'name': 'austria', 'country_code': 'at', 'calling_code': '43', 'digits': '8' },
    { 'name': 'great britian', 'country_code': 'gb', 'calling_code': '44', 'digits': '10' },
    { 'name': 'poland', 'country_code': 'pl', 'calling_code': '48', 'digits': '9' },
    { 'name': 'germany', 'country_code': 'de', 'calling_code': '49', 'digits': '9' }
  ],
  init: function() {
    this.form_el = SUPERREG.form_el;
    this.element = $('user_calling_code');
    this.element.observe('change', this.changeLocale.bind(this));
    this.changeHandler();
    //this.setupCountryLookup();
  },
  changeLocale: function(event) {
    window.top.location.href = '/signup?user[calling_code]=' + 
      this.form_el.down('#user_calling_code').getValue() + 
      '&user[login]=' + 
      this.form_el.down('#user_login').getValue();
  },
  changeHandler: function(event) {
    var value = this.element.value.toString();
    var country = this.findCountryFromNumber(value);
    this.changeCountry(country);
  },
  findCountryFromNumber: function(num) {
    var country = null;
    this.countries.each(function(c) {
      if(c['calling_code'].toString() == num.toString()) {
        country = c;
      }
    });
    if(country != null) {
      return country;
    } else {
      return false;
    };
  },
  findCountryFromName: function(name) {
    var country = null;
    var name = name;
    this.countries.each(function(c) {
      if(c.name.toString().toLowerCase() == name.toString().toLowerCase()) {
        country = c;
      }
    });
    if(country) {
      return country;
    } else {
      return false;
    };
  },
  sameCountry: function(c1,c2) {
    if(c1 == c2) {
      return true;
    } else {
      return false;
    }
  },
  changeFormClassName: function(country) {
    this.countries.each(function(c) {
      var hasClass = SUPERREG.form_el.hasClassName("country-code-"+c['calling_code']);
      if( hasClass == true && (c == country) == false ) {
        SUPERREG.form_el.removeClassName("country-code-"+c['calling_code']);
        // where does 'this' go inside of .each ? how to bind ?
      };
    });
    this.form_el.addClassName("country-code-"+country['calling_code']);
  },
  changeMobileNumberLength: function(country) {
    var mobilenumber_el = SUPERREG.form_fields['user_mobilenumber'].element;
    var mobilenumber_length = country['digits'];
    var new_element_value = mobilenumber_el.value;
    if(mobilenumber_el.getAttribute('maxlength').toString() != mobilenumber_length ) {
      if(mobilenumber_el.value.length > mobilenumber_length) {
        new_element_value = mobilenumber_el.value.substring(0,mobilenumber_length);
      };
      mobilenumber_el.setAttribute( 'maxlength', mobilenumber_length );
      mobilenumber_el.value = new_element_value;
    };
  },
  changeCountry: function(country) {
    if(country!=false) {
      this.changeFormClassName(country);
      this.changeMobileNumberLength(country);
      this.countryName = country['name'];
      this.countryCode = country['country_code'];
      this.callingCode = country['calling_code'];
      if(this.element.value != country['calling_code']) {
        this.element.value = country['calling_code'];
      }
    }
  },
  setupCountryLookup: function() {
    if(window.geoip_country_name) {
      // set country name based on user's geoip location
      this.geoipCountryName = window.geoip_country_name().toLowerCase();
      var country = this.findCountryFromName(this.geoipCountryName);
      if(country != false) {
        this.changeCountry(country);
      }
    } else {
      // run this function again in a few seconds to see if the script is loaded
      this.setTimeout("SUPERREG.CountryCheck.setupCountryLookup();", 2000);
    }
  }
};

// This polls a given URL for an expected result.
// If this result is obtained withing a given timeframe, a success function is executed.
SUPERREG.ResultPoller = {
  defaults: {
    // these options give a timeout of ~5 minutes (2 + 2.1 + 2.205 + ... + 17.111)
    interval: 2000, // msec
    growth:   1.05, // growth factor, interval is multiplied by this factor each iteration
    limit:    44,   // how many retries before timing out
    expected: 'true'
    // pollUrl:   '/foobar'
    // onSuccess: function() {}
    // onTimeout: function() {}
  },
  options: {},
  nextInterval: 0,
  tries: 0, 
  _handler: null,

  init: function(url, success, timeout, options) {
    this.options = $H(this.defaults).merge(options).merge({pollUrl: url, onSuccess: success, onTimeout: timeout}).toObject();
    this.nextInterval = this.options.interval;
    this.doCheck();
  },

  doCheck: function() {
    this.tries += 1;
    this.sendAjaxRequest(this.options.pollUrl);
  },

  reschedule: function() {
    try { window.console.log("retrying... " + this.tries); } catch(e) {}
    if (this.tries < this.options.limit) {
      this._handler = setTimeout(this.doCheck.bind(this), this.nextInterval);
      this.nextInterval *= this.options.growth;
    } else {
      this.options.onTimeout();
    }
  },

  sendAjaxRequest: function(requestURL) {
    return new Ajax.Request(requestURL, {
      method: 'post',
      onSuccess: function(transport) {
        var response = transport.responseText;
        if(response == this.options.expected) {
          this.options.onSuccess();
        } else {
          this.reschedule();
        }
      }.bind(this),
      onFailure: function(transport) {
        this.reschedule();
      }.bind(this)
    });
  }
}

SUPERREG.Functors = {
  redirect_to: function(url, isTop) {
    return function() {
      if (isTop) {
        window.top.location = url;
      } else {
        window.location = url;
      }
    }
  }
}

