(function () {

  YAHOO.namespace("applegate.registration");

  var Dom = YAHOO.util.Dom,
    $ = Dom.get,
    Event = YAHOO.util.Event,
    lang = YAHOO.lang,
    applegate = YAHOO.applegate,
    global = YAHOO.applegate.global,
    validation = applegate.validation,
    BA = Core.Widget.BlindAnimator;

  // Instantiate and configure Loader:
  var loader = new YAHOO.util.YUILoader({

    // Identify the components you want to load.  Loader will automatically identify
    // any additional dependencies required for the specified components.
    require: ["animation", "paginator"],

    // YUI Base directory
    base: '/javascript/yui-2.6.0/',

    // Configure loader to pull in optional dependencies.  For example, animation
    // is an optional dependency for slider.
    loadOptional: true,

    // The function to call when all script/css resources have been loaded
    onSuccess: function() {

      Event.onDOMReady(function () {
        YAHOO.log('Focus on the email field', 'info', 'register.js');
        var tb = new YAHOO.applegate.resources.TextBundle('ib_msg_i18n');

        function renderAutoCompleters() {
          YAHOO.log('Creating Town datasource', 'info', 'register.js');
          var dsTownAC = new applegate.dwr.DwrDataSource(RegistrationDwrModel.suggestTowns, [], {appendRequest: true});

          YAHOO.log('Creating County datasource', 'info', 'register.js');
          var dsCountyAC = new applegate.dwr.DwrDataSource(RegistrationDwrModel.suggestCounties, [], {appendRequest: true});

          YAHOO.log('Creating Town autocompleter', 'info', 'register.js');
          var acTown = new applegate.autocomplete.AutoComplete("cityTownNameInput", "townContainer", dsTownAC, {
            agSelectProperties: ["name"],
            agSuggestProperties: ["name"],
            agAllowEmptyQuery: true,
            agTrackingField: {field: "cityTown", property: "id"},
            minQueryLength: 0,
            forceSelection: true
          });

          YAHOO.log('Creating County autocompleter', 'info', 'register.js');
          var acCounty = new applegate.autocomplete.AutoComplete("countyNameInput", "countyContainer", dsCountyAC, {
            agSelectProperties: ["name"],
            agSuggestProperties: ["name"],
            agAllowEmptyQuery: true,
            agTrackingField: {field: "county", property: "id"},
            minQueryLength: 0,
            forceSelection: true
          });
        }

        function renderCountryAutocomplete() {
          YAHOO.log('Creating Country datasource', 'info', 'register.js');
          var dsCountryAC = new applegate.dwr.DwrDataSource(RegistrationDwrModel.suggestCountries, [], {appendRequest: true});

          YAHOO.log('Creating Country autocompleter', 'info', 'register.js');
          var acCountry = new applegate.autocomplete.AutoComplete("subscriberCountryName", "countryContainer", dsCountryAC, {
            agSelectProperties: ["name"],
            agSuggestProperties: ["name"],
            agAllowEmptyQuery: true,
            agTrackingField: {field: "subscriberCountry", property: "id"},
            minQueryLength: 0,
            forceSelection: true
          });
        }

        function bustCache() {
          var date = new Date();
          return date.getMilliseconds() + Math.random();
        }

        function handleNewCaptcha(p_oEvent) {
          YAHOO.applegate.captcha.handleNewCaptcha();
        }

        var findCompanyButton = new YAHOO.widget.Button($('findCompanyBtn'));
        var newCompanyButton = new YAHOO.widget.Button($('newCompany'));
        var submitRegistrationButton = new YAHOO.widget.Button('submitRegistration');
        var MAX_HEIGHT = 540;
        var myPaginator = new YAHOO.widget.Paginator({
          rowsPerPage: 5,
          totalRecords: 10,
          template: "{PreviousPageLink} <strong>{CurrentPageReport}</strong> {NextPageLink}",
          containers: ['pagination'],
          initialPage : 1
        });

        var clickEvent = {
          companySearch : function (o) {
            if (lang.trim($('findCompanyName').value) !== '' && lang.trim($('findPostcode').value) !== '') {
              findCompanyButton.set('disabled', true);
              loader.show(findCompanyButton);

              var myCallback = function () {
                this.set("sortedBy", null);
                var obj;
                try {
                  obj = YAHOO.lang.JSON.parse(myDataSource._oQueue.conn.conn.responseText);
                } catch (e) {
                  YAHOO.log('Error caught', 'error', 'register.js');
                }
                this.onDataReturnReplaceRows.apply(this, arguments);
                findCompanyButton.set('disabled', false);
                loader.hide(findCompanyButton);
                if (obj.postCodeError) {
                  applegate.dialog.showWarning(tb.getText(obj.postCodeError), "Post Code Error");
                } else if (obj.nameError) {
                  // Probably never get a nameError as the name is validated above and is the same validation as in the application.
                  applegate.dialog.showWarning(tb.getText(obj.nameError), "Company Name Error");
                }
                myPaginator.setState({rowsPerPage: 5, totalRecords: obj.totalResults});
                if(obj.totalResults > 0) {
                  this.selectRow(0);
                }
                window.setTimeout(function () {
                  Dom.setStyle('controllerDetails', 'height', ((MAX_HEIGHT + (myDataTable._elContainer.offsetHeight)) - 10) + 'px');
                }, 10);
              };
              var callback1 = {
                success : myCallback,
                failure : myCallback,
                scope : myDataTable
              };
              var companyName = lang.trim($('findCompanyName').value),
                postcode = lang.trim($('findPostcode').value);
                emailAddress = lang.trim($('email').value);
                myDataSource.sendRequest('findCompanyName=' + encodeURIComponent(companyName) + '&findPostcode=' + encodeURIComponent(postcode) + '&checkEmailAddress=' + encodeURIComponent(emailAddress) + '&t=' + bustCache(), callback1);
            } else {
              // else warn
              applegate.dialog.showWarning("You must enter both Company Name and Post Code to search on", "Company Name or Post Code not supplied");
            }
          },
          newCompany : function (o) {
            global.clearForm($('companyDetailsFieldset'));
            global.enableForm($('companyDetailsFieldset'));
            submitRegistrationButton.set('disabled', false);
          }
        };

        findCompanyButton.on("click", clickEvent.companySearch);
        newCompanyButton.on("click", clickEvent.newCompany);
        submitRegistrationButton.on("click", handleRegister);

        function handleRegister(p_oEvent) {
          document.body.style.cursor = 'wait';
          submitRegistrationButton.set('disabled', true);
          // short hand
          var form = Dom.get('registrationForm');
          validation.clearMessages(form);
          var YUC = YAHOO.util.Connect;
          YUC.setForm(form);

          YUC.asyncRequest('POST', global.contextPath() + "/register.json", {
            success: handleRegisterSuccess,
            failure: handleRegisterFailure,
            scope: this
          });
        }

        var handleRegisterSuccess = function (o) {
          var obj = lang.JSON.parse(o.responseText),
             form = Dom.get('registrationForm');
          if (obj.hasErrors) {
            validation.applyBindingResultToForm(obj, form);
            Dom.setStyle('messageTitle', 'visibility', 'visible');
            YAHOO.applegate.captcha.handleNewCaptcha();
            $('captcha').value = '';
            document.body.style.cursor = 'default';
            submitRegistrationButton.set('disabled', false);
            window.scrollTo(0,0);
          } else {
            validation.clearMessages(form);
            location.href = global.contextPath() + '/' + obj.view;
          }
        };

        var handleRegisterFailure = function (o) {
          applegate.dialog.showWarning("Your registration failed. Please try again or contact us.", "Registration Failed");
          YAHOO.applegate.captcha.handleNewCaptcha();
          submitRegistrationButton.set('disabled', false);
          document.body.style.cursor = 'default';
        };

        YAHOO.log('Set JavaScript refresh code for newCaptchaImg', 'info', 'registration.js');
        Event.addListener("newCaptchaImg", "click", handleNewCaptcha);

        var controllerExpanded = false,
          anim = BA('controllerDetails', {maxHeight: MAX_HEIGHT, animSpeedDown: 1, animSpeedUp: 1, easing: YAHOO.util.Easing.easeOut});

        anim.subscribe('_onStart', function () {
          Dom.setStyle('controllerDetails', 'display', 'block');
          Dom.setStyle('controllerDetails', 'visibility', 'visible');

          Dom.setStyle('subscriberDetails', 'display', 'none');
          if($('firstName').value == '') {
            $('firstName').value = $('subscriberFirstName').value;
          }

          if($('lastName').value == '') {
            $('lastName').value = $('subscriberLastName').value;
          }

          Dom.removeClass('controllerMoreInfo', 'controllerMoreInfoClosed');
          Dom.addClass('controllerMoreInfo', 'controllerMoreInfoOpen');

          $('registrationType').value = 'CONTROLLER';
        });

        anim.subscribe('_onComplete', function () {
          Dom.setStyle('controllerDetails', 'display', 'none');
          Dom.setStyle('controllerDetails', 'visibility', 'hidden');

          Dom.setStyle('subscriberDetails', 'display', 'block');
          if($('subscriberFirstName').value == '') {
            $('subscriberFirstName').value = $('firstName').value;
          }

          if($('subscriberLastName').value == '') {
            $('subscriberLastName').value = $('lastName').value;
          }

          Dom.removeClass('controllerMoreInfo', 'controllerMoreInfoOpen');
          Dom.addClass('controllerMoreInfo', 'controllerMoreInfoClosed');
          $('registrationType').value = 'ASM_USER';
        }, true);

        anim.subscribe('_onStart', function () {
          var autocompleters = ['companySearchResults', 'townAc', 'countyAc', 'findCompanyBtn', 'newCompany'];

          global.forEach(autocompleters, function (ac) {
            Dom.setStyle(ac, 'display', 'none');
          });
        }, true);

        anim.subscribe('_onComplete', function () {
          var autocompleters = ['townAc', 'countyAc'];

          global.forEach(autocompleters, function (ac) {
            Dom.setStyle(ac, 'display', 'inline');
          });

          autocompleters = ['findCompanyBtn', 'newCompany'];

          global.forEach(autocompleters, function (ac) {
            Dom.setStyle(ac, 'display', 'inline-block');
          });

          Dom.setStyle('companySearchResults', 'display', 'block');
          Dom.setStyle('companySearchResults', 'visibility', 'visible');

          if (controllerExpanded === false) {
            renderDatatable();
            renderAutoCompleters();
            controllerExpanded = true;
          }
        }, false);

        renderCountryAutocomplete();

        function handleExpandControllerDetails(p_oEvent) {
          anim.toggle();
        }

        Event.addListener("controllerMoreInfo", "click", handleExpandControllerDetails);

        var myDataSource = null,
          myDataTable = null,
          loaderSpan = null;

        var loader = {
          show: function (elm) {
            loaderSpan = document.createElement('span');
            loaderSpan.setAttribute('id', Dom.generateId());
            loaderSpan.setAttribute('title', 'Searching...');
            Dom.addClass(loaderSpan, 'registrationLoader');

            elm.appendChild(loaderSpan);
          },
          hide: function (elm) {
            elm.removeChild(loaderSpan);
          }
        };

        function selectRowEvent(oArgs) {
          var record = this.getRecord(oArgs.el);
          var id = record.getData('id');

          var companyCallback = function (company) {
            if (company !== null && typeof company === 'object') {
              global.populateForm(company, $('companyDetailsFieldset'));
              global.disableForm($('companyDetailsFieldset'));

              // If there is any form of controller, active or pending, then disable the register button
              if (record.getData('hasController') === true || record.getData('hasControllerValidationPending') === true) {
                submitRegistrationButton.set('disabled', true);
              } else {
                submitRegistrationButton.set('disabled', false);
              }
            }
          };
          RegistrationDwrModel.findCompanyById(id, companyCallback);
        }

        function renderDatatable() {
          this.hasControllerFormatter = function (elCell, oRecord, oColumn, sData) {
            if (oRecord.getData("hasController")) {
              var emailAddress = document.getElementById("email").value;
              var name = lang.trim(document.getElementById("firstName").value) + " " + lang.trim(document.getElementById("lastName").value);
              elCell.innerHTML = '<a href="/account/contactUs.html?companyId=' + oRecord.getData("id") + '&ref=registration&emailAddress=' + emailAddress + '&name='+ name +'" title="Contact us about this" target="_blank">This company has a controller</a>';
            } else if (oRecord.getData("hasControllerValidationPending")) {
              var emailAddress = document.getElementById("email").value;
              var name = lang.trim(document.getElementById("firstName").value) + " " + lang.trim(document.getElementById("lastName").value);
              elCell.innerHTML = '<a href="/account/contactUs.html?companyId=' + oRecord.getData("id") + '&ref=registration&emailAddress=' + emailAddress + '&name='+ name +'" title="Contact us about this" target="_blank">This company has a controller registration pending</a>';
            }
          };
          var myColumnDefs = [
            {key: "name", label: "Name", sortable: true, width: 260},
            {key: "town", label: "Town/City", sortable: true, width: 100},
            {key: "postcode", label: "Post Code", sortable: true, width: 70},
            {label: '', sortable: false, formatter: this.hasControllerFormatter, width: 220}
          ];

          myDataSource = new YAHOO.util.DataSource(global.contextPath() + '/companySearch/search.html?');
          myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
          myDataSource.connXhrMode = "queueRequests";
          myDataSource.responseSchema = {
            resultsList: "results",
            fields: ["name", "town", "postcode", "hasController", "hasControllerValidationPending", "id"]
          };

          var oConfigs = {
            paginator : myPaginator,
            initialLoad: false
          };

          myDataTable = new applegate.datatable.DataTable('companySearchResults', myColumnDefs, myDataSource, oConfigs);

          // Enables single-mode row selection
          myDataTable.set("selectionMode", "single");
          myDataTable.subscribe("rowSelectEvent", selectRowEvent);
        }

        if ($('ref').value === 'PUBLIC_COMPANY_PAGE') {
          anim.toggle();
          if (lang.trim($('findCompanyName').value) !== '' && lang.trim($('findPostcode').value) !== '') {
            window.setTimeout(function () {
              clickEvent.companySearch();
            }, 1000);
          }
        }

        if ($('registrationType').value === 'CONTROLLER' || $('currentUserStatus').value === 'LOGGED_IN' || $('currentUserStatus').value === 'PARTIALLY_LOGGED_IN') {
          anim.blindDown();
        }

        if ($('currentUserStatus').value === 'LOGGED_IN' || $('currentUserStatus').value === 'PARTIALLY_LOGGED_IN') {
          // Disable the email address because they must have one to be (partially) logged in
          $('email').readOnly = true;
          Dom.addClass('email', 'disabled');
          // Hide the link if they are fully/partially logged in because it's redundant
          Dom.setStyle('already_registered', 'display', 'none');

          // Disable first and last name if they are present
          if (lang.trim($('firstName').value) !== '') {
            $('firstName').readOnly = true;
            Dom.addClass('firstName', 'disabled');
          } else {
            window.setTimeout(function () {
              $('firstName').focus();
            }, 100);
          }

          if (lang.trim($('lastName').value) !== '') {
            $('lastName').readOnly = true;
            Dom.addClass('lastName', 'disabled');
          }else if($('firstName').readOnly){
            window.setTimeout(function () {
              $('lastName').focus();
            }, 100);
          }

          if ($('firstName').readOnly && $('lastName').readOnly) {
            window.setTimeout(function () {
              $('jobTitle').focus();
            }, 100);
          }
        }
        if(!$('email').readOnly) {
          $('email').focus();
        }
      });
    },

    //Set your skins member here:
    skin: {
      // The default skin, which is automatically applied if not
      // overriden by a component-specific skin definition.
      // Use the Applegate specific skin.
      defaultSkin: 'applegate'
    },

    // Configure the Get utility to timeout after 10 seconds for any given node insert
    timeout: 10000,

    // Combine YUI files into a single request (per file type) by using the Yahoo! CDN combo service.
    combine: false
  });

  // Load the files using the insert() method. The insert method takes an optional
  // configuration object, and in this case we have configured everything in
  // the constructor, so we don't need to pass anything to insert().
  loader.insert();

})();