var Survey = {
  conditionalTriggers: new Object(),
  requestedSkipForm: false,
  validSubmission: true,
  hasBeenSubmitted: false,
  elementValidations: new Object(),
  errorsById: new Object(),
  offersToPopup: (new Object()),
  hasPopped: false,
  errorIds: new Array(),

  showElement: function(elementID) {
    var domID = '#e' + elementID;
    $(domID + '-wrapper').fadeIn(500);
    $(domID + '-is-visible').val('true');
  },

  hideElement: function(elementID) {
    var domID = '#e' + elementID;
    var wrapperID = domID + '-wrapper';

    $(wrapperID).fadeOut(250);
    $(domID + '-is-visible').val('false');
    $(':text, :password, :file', wrapperID).val('');
    $(':input,select option', wrapperID).removeAttr('checked').removeAttr('selected');
  },

  addRules: function(elementID, valIDs) {
    var domID = '#e' + elementID;
    var elem = $(domID);
    elem.bind('blur', function(ev){
      elem.busy();
      setTimeout(function(){ elem.busy('hide'); }, 5 * 1000);

      ah.send({
        ruler_action: 'validate',
        visitor_id: $.cookie('_vid') || '-',
        dom_id: $(this).attr('id'), // spinner is applied to this
        element_id: elementID,
        validation_ids: valIDs,
        value: $(this).val()
      });
    })

    var autoDomID = domID + '_auto';
    elem = $(autoDomID);
    elem.bind('blur', function(ev){
      elem.busy();
      setTimeout(function(){ elem.busy('hide'); }, 5 * 1000);

      ah.send({
        ruler_action: 'validate',
        visitor_id: $.cookie('_vid') || '-',
        dom_id: autoDomID,
        element_id: elementID,
        validation_ids: valIDs,
        value: $(this).val()
      });
    })

    return true;
  },

  // Tracks event in Google
  track: function(opts) {
    var me = this;

    var
      commandArray = opts['info'],
      gaTrackers = opts['gaTrackers'],
      selector = opts['selector'],
      jsEvent = opts['jsEvent'];

    $(function(){
      $(selector).bind(jsEvent, function(evt){
        try{
          // Google
          if (gaTrackers) {
            for( var i = 0; i < gaTrackers.length; i++ ) {
              commandArray.unshift(gaTrackers[i]+'._trackEvent');
              _gaq.push(commandArray);
            }
          }
        }catch(err){}

        return true;
      });
    });

    return me;
  },

  skipForm: function() {
    this.requestedSkipForm = true;
    return true;
  },

  addValidation: function(elementId, valType, valMessage) {
    var key = 'e' + elementId;
    if (Survey.elementValidations[key] == undefined) Survey.elementValidations[key] = new Object();

    var valParams = [];
    for( var i = 3; i < arguments.length; i++ ) {
      valParams.push(arguments[i])
    }

    Survey.elementValidations[key][valType] = {valMessage: valMessage, valParams: valParams};
  },

  validateForm: function() {
    // Don't allow multiple form submissions - returning false will stop the form from being submitted
    if (this.hasBeenSubmitted) return false;

    if (this.requestedSkipForm) return true;

    var validSubmission = true;

    Survey.errorIds = new Array();

    for (var elemIdString in this.elementValidations) {
      if (elemIdString != 'size') {
        var jqWrapper = jQuery('#' + elemIdString + '-wrapper');

        var errorMessages = new Array();

        var container = jqWrapper.parents('.expandable-container')
        var containerIsVisible = (container.length == 0 || container.is(':visible'))
        if (!containerIsVisible) {continue}

        var isVisible = (jQuery('#' + elemIdString + '-is-visible').val() == 'true');
        if (!isVisible) {continue;};

        var curVal = this._formValueFor(elemIdString);
        var isBlank = this._isBlankString(curVal);

        var validations = this.elementValidations[elemIdString]
        var val;

        // Required
        val = validations['RequiredValidation'];
        if (val != undefined && isBlank) {
          errorMessages.push(val.valMessage);
        }

        // Date
        val = validations['DateValidation'];
        if (!isBlank && val != undefined) {
          var d = parseDate(curVal);
          if (!d) errorMessages.push(val.valMessage);
        }

        // Number
        val = validations['NumberValidation'];
        var numberRe = /^[+-]?[0-9]+$/
        if (!isBlank && val != undefined) {
          if (!numberRe.test(curVal)) errorMessages.push(val.valMessage);
        }

        // MinimumLength
        val = validations['MinimumLengthValidation'];
        var minLengthRe = /^\S{6,}$/
        if (!isBlank && val != undefined) {
          if (!minLengthRe.test(curVal)) errorMessages.push(val.valMessage);
        }

        // Regexps
        var revals = ['EmailValidation', 'PhoneValidation', 'ZipValidation', 'RegexpValidation'];
        for (var i=0; i<revals.length; i++) {
          val = validations[revals[i]];
          if (!isBlank && val != undefined) {
            var re = new RegExp(val.valParams[0], val.valParams[1]);
            if (!re.test(curVal)) errorMessages.push(val.valMessage);
          }
        }

        if (jqWrapper.hasClass('field-with-errors')) {
          errorMessages.push('error');
        }

        if (errorMessages.length == 0) {
          // this._clearErrors(elemIdString)

        } else {
          validSubmission = false;
          Survey.displayError(elemIdString, errorMessages);
        }
      }
    }

    // This will catch errors created from the server - autocomplete
    validSubmission = validSubmission && ($('.field-with-errors').length < 1)

    if (!validSubmission) {
      this.validSubmission = false;
      alert("There were some problems with the submitted information.\n\nPlease look over the form and correct the issues before continuing.")
      return false;
    }

    // Everything was valid, and we'll be submitting the form - clean up all defaults
    jQuery('input[default]').each(function(){
      var input = $(this)
      if (input.val() == input.attr('default') && input.hasClass('default')) {
        input
          .removeClass('default')
          .val('')
      }
    })

    this._popupOffers();

    this.validSubmission = true;

    // Don't allow them to submit the form multiple times
    this.hasBeenSubmitted = true;

    return true;
  },

  displayError: function(elemIdString, errorMessages) {
    var jqWrapper = jQuery('#' + elemIdString + '-wrapper');

    jqWrapper.addClass('error-wrapper')

    var groupWrapper = jqWrapper.find('.group:eq(0)')

    // Bling style - with group divs
    if (groupWrapper.length > 0) {
      var jqErrorMessageContainer = groupWrapper.find('p.error')

      if (jqErrorMessageContainer.length == 0) {
        groupWrapper.append('<p class="error"></p>')
        jqErrorMessageContainer = groupWrapper.find('p.error')
      }

      jqErrorMessageContainer.html(errorMessages[0])

    // NewUI stuff
    } else {
      var jqErrorMessageContainer = jqWrapper.find('p.error');
      if (jqErrorMessageContainer.length > 0) {
        jqErrorMessageContainer.html(errorMessages[0]);
      } else {
        jqWrapper.append('<p class="error">' + errorMessages[0] + '</p>');
      }
    }

    jqWrapper.find('input:not(:hidden,:image,:radio,:checkbox),select,textarea')
      .addClass('field-with-errors')
      .removeClass('field-being-fixed')

    var label = jqWrapper.find('label:eq(0)')
    var name = ''
    if (label.size != 0)
      name = label.attr('title')
    Survey.errorsById[elemIdString] = {'name': name, 'messages': errorMessages}

    Survey.errorIds.push(elemIdString.replace('e',''));

    return true;
  },

  displayMessage: function(msg) {
    alert(msg)
  },

  _isOriginalEvent: function(e) {
    // if no event - it is not the original
    if (e == undefined) return false
    return (
        (jQuery.browser.msie && (e.returnValue == undefined)) ||
        (jQuery.browser.safari) ||
        (e.cancelable)
        );
  },

  _isElementVisible: function(elementId) {
    var key = 'e' + elementId;
    if (this.conditionalTriggers[key] && (Object.size(this.conditionalTriggers[key]) != 0)) {
      return true
    }
    return false;
  },

  _setElementTrigger: function(elementId, triggerValue, needToShow) {
    var elementWasVisible = this._isElementVisible(elementId);

    var key = 'e' + elementId;
    if (needToShow) {
        if (!this.conditionalTriggers[key]) this.conditionalTriggers[key] = new Object();
        this.conditionalTriggers[key]['t' + triggerValue] = true;
    } else {
        if (!elementWasVisible) return false;
        delete this.conditionalTriggers[key]['t' + triggerValue];
    }
    return elementWasVisible;
  },

  _clearFormValues: function(elementId) {
    var me = this;
    jQuery('#e' + elementId + '-wrapper').find('input,select').each( function() { me._clearFormValue(this); } ).change();
  },

  _clearFormValue: function(domElement) {
    switch (domElement.nodeName) {
      case 'INPUT' :
      switch (domElement.type) {
        case 'checkbox' :
        case 'radio'    : domElement.checked = false; break;
        case 'password' :
        case 'text'     : domElement.value = ''; break;
      }
      break;
      case 'SELECT' : domElement.selectedIndex = 0; break;
    }

  },

  _processChange: function(conditionalElementIdsString, needToShow, triggerElementValue) {
    if (conditionalElementIdsString == undefined || conditionalElementIdsString == null || conditionalElementIdsString.length < 1) return;

    var conditionalElementIds = conditionalElementIdsString.split(',');

    for (var index=0; index<conditionalElementIds.length; index++) {
      var elemId = conditionalElementIds[index];
      var domId = "e" + elemId;

      var elementWasAlreadyVisible = this._setElementTrigger(elemId, triggerElementValue, needToShow);
      var elementIsNowVisible = this._isElementVisible(elemId);

      if (needToShow && elementIsNowVisible) {
        if (!jQuery('#e' + elemId + '-wrapper').hasClass('hidden-value-wrapper')) {
          jQuery('#e' + elemId + '-wrapper').slideDown(250);
        }

        jQuery('#e' + elemId + '-is-visible').val(true);

      } else if (!needToShow && !elementIsNowVisible) {
        if (!jQuery('#e' + elemId + '-wrapper').hasClass('hidden-value-wrapper')) {
          jQuery('#e' + elemId + '-wrapper').slideUp(250);
        }
        jQuery('#e' + elemId + '-is-visible').val(false);
        this._clearErrors('e' + elemId)
        this._clearFormValues(elemId);
      }
    }
  },

  __handleEvent: function(triggerEvent, triggerElement, triggerElementId, conditionalElementIdsString) {
    var optId = triggerElement.value;

    if (triggerElement.type == 'checkbox') {
      var actType = triggerElement.checked ? 'check' : 'uncheck';
      this._processChange(conditionalElementIdsString, triggerElement.checked, triggerElement.value);

    } else if (triggerElement.type == 'radio') {
      if (this._isOriginalEvent(triggerEvent)) {
        var actType = triggerElement.checked ? 'check' : 'uncheck';

        triggerEvent.returnValue = true; // needed for IE
        this._processChange(conditionalElementIdsString, triggerElement.checked, triggerElement.value);

        // Now loop through all other radio buttons and fire the onchange for them
        jQuery('.e' + triggerElementId + '-option').not(triggerElement).each(function(){
          this.onchange();
        });

      } else {
        this._processChange(conditionalElementIdsString, triggerElement.checked, triggerElement.value);
      }
    }
    return true;
  },

  __handleSelectChange: function(selectElement) {
    var selElem = $(selectElement);

    var me = this;
    selElem.find('option').each(function(){ me._processChange(jQuery(this).attr('conditionalElements'), this.selected, this.value) });
    return true;
  },

  __addConditionalTrigger: function(elementId, triggerValue) {
    this._setElementTrigger(elementId, triggerValue, true)
  },


  addPopup: function(offerId, opts) {
    this.offersToPopup[offerId] = opts
  },

  selectPopup: function(offerId) {
    if (this.offersToPopup[offerId] == undefined) return;

    this.offersToPopup[offerId]['selected'] = true
  },

  _popupOffers: function() {
    if (this.hasPopped == true) return;

    jQuery.each(this.offersToPopup, function(offerId, opts){
      if (opts['selected'] == true) {
        var title = "popup" + offerId;
        window.open(opts['url'], title, opts['popup_options']);
      }
    })

    this.hasPopped = true;
    return false
  },

  _isBlankString: function(s) {
    var blankRE = /^[\s]+jQuery/;
    return (s == "" || blankRE.test(s));
  },

  _formValueFor: function(elemIdString) {
    var me = this;
    var curVal = '';

    var wrapper = jQuery('#' + elemIdString + '-wrapper')

    if (wrapper.hasClass('date-question-wrapper')) {
      var dayElem = jQuery('#' + elemIdString + '-day')
      var monthElem = jQuery('#' + elemIdString + '-month')
      var yearElem = jQuery('#' + elemIdString + '-year')

      var day = ''
      var month = ''
      var year = ''

      // This is used to determine if they entered ANYTHING for this date element
      var presentedValue = '';

      // Day wasn't present - default it so validation will pass
      if (dayElem.length == 0) {
        day = '01';

      } else {
        day = dayElem.val();

        // Was present, but was left blank
        if (day == '' || day == 'Day') {
          day = '';
        }

        presentedValue += day;
      }


      // Month wasn't present - default it so validation will pass
      if (monthElem.length == 0) {
        month = '01';

      } else {
        month = monthElem.val();

        // Was present, but was left blank
        if (month == '' || month == 'Month') {
          month = '';
        }

        presentedValue += month;
      }


      // Year wasn't present - default it so validation will pass
      if (yearElem.length == 0) {
        year = '2000';

      } else {
        year = yearElem.val();

        // Was present, but was left blank
        if (year == '' || year == 'Year') {
          year = '';
        }

        presentedValue += year;
      }

      var str = day + '/' + month + '/' + year;

      // They didn't enter anything
      if (presentedValue == '') {
        return '';

      } else {
        return str;
      }

    } else {
      jQuery('#' + elemIdString + '-wrapper').find('input:not(:hidden,:image),select,textarea').each( function() {
        switch (this.nodeName) {
          case 'INPUT' :
          switch (this.type) {
            case 'checkbox' :
            case 'radio'    : if (this.checked) curVal += this.value; break;
            case 'password' :
            case 'text'     : if (jQuery(this).hasClass('default')){curVal = ''}else{curVal = this.value}; break;
          }
          break;
          case 'SELECT' : curVal = jQuery(this).val(); break;
          case 'TEXTAREA' : curVal = jQuery(this).val(); break;
        }
      });

      return curVal;
    }
  },

  _clearErrors: function(elemIdString) {
    var posWrapper = jQuery('#' + elemIdString + '-wrapper')
    posWrapper.removeClass('error-wrapper')
    posWrapper.find('p.error').remove()
    posWrapper.find('.field-with-errors').removeClass('field-being-fixed field-with-errors')
  },

  tabContent: function(groupID, tabName) {
    $("#" + groupID + "-content-wrapper .content-tab").hide();
    $("#" + groupID + "-tabs > li").removeClass('active')
    $("#" + groupID + "-" + tabName + "-tab").addClass('active')
    $("#" + groupID + "-" + tabName + "-content").show();

    return false;
  }
}

