var pensionCalculator = new PensionCalculator();

function PensionCalculator() {

   var name = "Pension Calculator";   
   var calculatorURL = "/pension-sales-web/pensionCalculator/GetPensionCalculation.do";
   var assumptionsPopupURL = "/virgin/pension/popups/pensionCalculatorAssumptions.jsp";
   var childAssumptionsPopupURL = "/virgin/pension/popups/pensionCalculatorAssumptionsChild.jsp";
   var genericErrorObject = {"errorMessage":{"errorMessageKey":"genericException","errorDefaultMessage":"Unable to retrieve pension calculation<p>For calculations where there's less than ten years between current age and retirement age, call us on 08456 10 20 40</p>"}};
   var pensionCalculationResult = null;
   var properties = new Hash();
   var effects = new Effects();

   this.prepopulateValuesFromCookies = prepopulateValuesFromCookies;

   function prepopulateValuesFromCookies() {
      $$(".inputCalculatorParameter").each(function(s){
         var name = s.name.split('.');
         var persistedValue = getCookieValue(name[0] + "." + name[1]).split('=')[1];

         if (persistedValue) {
            if (s.type == 'radio') {
               if (s.value == persistedValue) {
                  s.checked = true;
               }
            } else {
               s.value = persistedValue;
            }
         }
      });
   }

   this.getPensionCalculation = getPensionCalculation;

   function getPensionCalculation() {
      if (checkForInputsUpdate()) {
         getEffects().clearFieldErrors();
         if ($('employerpayments-content')) {
            if ($('employerpayments-content').style.display == 'none') {
               $('employerLumpSumAmount').value = "";
               $('employerRegularPaymentAmount').value = ""; 
            }
         }

         $$('.inputCalculatorParameter').each(function(s) {
            if (s.type == 'radio' && s.checked == true) {
               handleRadioInputs(s.name, s.value);         
            } else if(s.type != 'radio'){
               if (s.name == "pensionCalculation.regularPaymentAmount" || s.name == "pensionCalculation.lumpSumAmount") {
                  var value = s.value.replace("£", "").replace("\.00", "");
                  properties.set(s.name, value);
               } else {
                  properties.set(s.name, s.value);
               }
            }
         });

         effects.showLoadingScreen('calculatorpanel-content');
         new Ajax.Request(calculatorURL, {parameters:  properties,
                                          onSuccess:   onSuccess,
                                          onFailure:   onFailure,
                                          onException: onException,
                                          onCreate:    onCreate,
                                          onComplete:  onComplete});                     

      } else {
         displayCalculationResults(pensionCalculationResult.pensionCalculationResultWrapper.calculationResults);
         getEffects().showResultsPanel();
      }
   }

   function handleRadioInputs(name, value) {   
      var fragments = name.split('.');
      var propertyName = fragments[0] + "." + fragments[1];
      properties.set(propertyName, value);
   }

   this.getCalculatorURL = getCalculatorURL;

   function getCalculatorURL() {
      return calculatorURL;
   }

   this.setCalculatorURL = setCalculatorURL;

   function setCalculatorURL(url) {
      calculatorURL = url;
   }

   this.getAssumptionsPopupURL = getAssumptionsPopupURL;

   function getAssumptionsPopupURL() {
      return assumptionsPopupURL;
   }

   this.setAssumptionsPopupURL = setAssumptionsPopupURL;

   function setAssumptionsPopupURL(url) {
      assumptionsPopupURL = url;
   }

   this.getPensionCalculationResult = getPensionCalculationResult;

   function getPensionCalculationResult() {
      return pensionCalculationResult;
   }

   function handleResponseErrors(errors) {
      try {
         errors.errorMessage.each(function(s) {
            $(s.errorMessageKey).innerHTML = s.errorDefaultMessage;
            $(s.errorMessageKey).parentNode.style.display = "block";
            var crossKey = s.errorMessageKey.split('.');
            if (crossKey.length < 2) {
               var crossKeyId = $(crossKey[0] + ".cross");
               if (crossKeyId) {
                  crossKeyId.style.display = "inline";
               } else {
                  var crosses = document.getElementsByName(crossKey[0] + ".cross");
                  for (var i = 0; i < crosses.length; i++) {
                     crosses[i].style.display = "inline";
                  }
               }
            } else {
               var crossKeyId = $(crossKey[0] + "." + crossKey[1] + ".cross");
               if (crossKeyId) {
                  crossKeyId.style.display = "inline";
               } else {
                  var crosses = document.getElementsByName(crossKey[0] + "." + crossKey[1] + ".cross");
                  for (var i = 0; i < crosses.length; i++) {
                     crosses[i].style.display = "inline";
                  }
               }
            }
         });   
      } catch(err) {
         $(errors.errorMessage.errorMessageKey).innerHTML = errors.errorMessage.errorDefaultMessage;
         $(errors.errorMessage.errorMessageKey).parentNode.style.display = "block";   
         var crossKey = errors.errorMessage.errorMessageKey.split('.');
         if (crossKey.length < 2) {
            var crossKeyId = $(crossKey[0] + ".cross");
            if (crossKeyId) {
               crossKeyId.style.display = "inline";
            } else {
               var crosses = document.getElementsByName(crossKey[0] + ".cross");
               for (var i = 0; i < crosses.length; i++) {
                  crosses[i].style.display = "inline";
               }
            }
         } else {
            var crossKeyId = $(crossKey[0] + "." + crossKey[1] + ".cross");
            if (crossKeyId) {
               crossKeyId.style.display = "inline";
            } else {
               var crosses = document.getElementsByName(crossKey[0] + "." + crossKey[1] + ".cross");
               for (var i = 0; i < crosses.length; i++) {
                  crosses[i].style.display = "inline";
               }
            }
         }
      }
   }

   function displayCalculationResults(results) {
      $('totalWithoutEscalation').innerHTML = "&pound;" + results.actualValuesWithoutEscalation.fundValue;
      $('annualWithoutEscalation').innerHTML = "&pound;" + results.actualValuesWithoutEscalation.annualPension;
      $('totalWithEscalation').innerHTML = "&pound;" + results.actualValuesWithEscalation.fundValue;
      $('annualWithEscalation').innerHTML = "&pound;" + results.actualValuesWithEscalation.annualPension;
      $('todaysWithoutEscalation').innerHTML = "&pound;" + results.todaysMoneyWithoutEscalation.annualPension;
      $('todaysWithEscalation').innerHTML = "&pound;" + results.todaysMoneyWithEscalation.annualPension;
      $('retirementYear').innerHTML = results.retirementYear;
      $('costOfDelay').innerHTML = results.costOfDelay.costOfDelayAmount;
   }

   function updateResultField(name, value) {
      $(name).innerHTML = value;
   }

   function checkForInputsUpdate() {
      if (properties.size() == 0) return true;
      var result = true
      var inputs = $$('.inputCalculatorParameter');
      inputs.each(function(s) {
         if (s.type == 'radio' && s.checked == false) return; //behaves like continue
            var name = s.name.split('.');
            if (!properties.get(name[0] + "." + name[1]) == s.value) {
               //result = true;
            }
         });
      return result;
   }

   this.exclusiveRadioButton = exclusiveRadioButton;

   function exclusiveRadioButton(group, radio) {
      $$('.' + group).each(function(s){
         if (s.name != radio.name) {
            s.checked = false;
         }
      });      
   }

   this.displayAssumptions = displayAssumptions;

   function displayAssumptions() {
      var retirementYear = pensionCalculationResult.pensionCalculationResultWrapper.calculationResults.retirementYear;
      var finalIncrementingPaymentAmount = pensionCalculationResult.pensionCalculationResultWrapper.calculationResults.actualValuesWithEscalation.finalRegularPaymentAmount;
      var url = assumptionsPopupURL + "?finalIncrementingPaymentAmount=" + finalIncrementingPaymentAmount + "&retirementYear=" + retirementYear;
      OpenNew(url, "assumptionsPopup", 600, 500);
   }

   this.displayAssumptionsChild = displayAssumptionsChild;

   function displayAssumptionsChild() {
      var retirementYear = pensionCalculationResult.pensionCalculationResultWrapper.calculationResults.retirementYear;
      var finalIncrementingPaymentAmount = pensionCalculationResult.pensionCalculationResultWrapper.calculationResults.actualValuesWithEscalation.finalRegularPaymentAmount;
      var url = childAssumptionsPopupURL + "?finalIncrementingPaymentAmount=" + finalIncrementingPaymentAmount + "&retirementYear=" + retirementYear;
      OpenNew(url, "assumptionsPopup", 600, 500);
   }

   this.openHelpPopup = openHelpPopup;

   function openHelpPopup(url) {
      OpenNew(url, "helpPopup", 600, 200);
   }

   function persistInputValues() {
      properties.each(function(s){
         document.cookie = s.key + "=" + s.value + ";";
      });
   }

   function onSuccess(transport) {
      pensionCalculationResult = transport.responseText.evalJSON();
      if (pensionCalculationResult.pensionCalculationResultWrapper.ok == 'false') {
         handleResponseErrors(pensionCalculationResult.pensionCalculationResultWrapper.errors);
      } else {
         displayCalculationResults(pensionCalculationResult.pensionCalculationResultWrapper.calculationResults);      
         getEffects().showResultsPanel();
         persistInputValues();
      }
      getEffects().removeLoadingScreen();
   }

   function onFailure(transport, exception) {
      handleResponseErrors(genericErrorObject);
      getEffects().removeLoadingScreen();
   }

   function onException(transport, exception) {
      handleResponseErrors(genericErrorObject);
      getEffects().removeLoadingScreen();
   }

   function onCreate(transport) {
   }

   function onComplete(transport) {
   }

   this.getEffects = getEffects;

   function getEffects() {
      return effects;
   }

//================================================= EFFECTS SUBSYSTEM =================================================//

   function Effects() {
      var slideDuration = 1.5;
      var loadingDivId = 'loadingDiv';
      var loadingOpacity = 0.4;
      var calculatorPanelPadding = 2;
      var resultsPanelLink = "javascript:pensionCalculator.getPensionCalculation();";
      var calculatorPanelLink = "javascript:pensionCalculator.getEffects().showCalculatorPanel();";

      //============================================ CREATE IMAGE CACHE ============================================//

      var imageCache = new Array();

      var expandHeaderMinus = new Image();
      expandHeaderMinus.src = '/virgin/Images/expand-header-minus_tcm23-5184.gif';
      imageCache['/virgin/Images/expand-header-minus_tcm23-5184.gif'] = expandHeaderMinus;   

      var expandHeaderPlus = new Image();
      expandHeaderPlus.src = '/virgin/Images/expand-header-plus_tcm23-5185.gif';
      imageCache['/virgin/Images/expand-header-plus_tcm23-5185.gif'] = expandHeaderPlus;

      var downArrow = new Image();
      downArrow.src = '/virgin/Images/dropdown-arrow_tcm23-5183.gif';
      imageCache['/virgin/Images/dropdown-arrow_tcm23-5183.gif'] = downArrow;   

      var questionArrow = new Image(); 
      questionArrow.src = '/virgin/Images/dropdown-arrow-off_tcm23-5182.gif';
      imageCache['/virgin/Images/dropdown-arrow-off_tcm23-5182.gif'] = questionArrow;   

      var loading = new Image();
      loading.src = '/virgin/Images/loading_tcm23-5187.gif';
      imageCache['/virgin/Images/loading_tcm23-5187.gif'] = loading;

      //============================================ CREATE IMAGE CACHE ============================================//

      this.switchPanelVisibility = switchPanelVisibility;
      
      function switchPanelVisibility(element, imageID, onImage, offImage) {
         if ($(element).style.display == "none") {
            displayPanel($(element));
            setImage(imageID, onImage)
         } else {
            hidePanel($(element));
            setImage(imageID, offImage);
         }
      }

      this.showResultsPanel = showResultsPanel;

      function showResultsPanel() {
         $('calculatorPanelLink').href = calculatorPanelLink;
         $('resultsPanelLink').href = "javascript:void(0);";
         slideUp('calculatorpanel-content');
         setImage('calculator-header-arrow', '/virgin/Images/dropdown-arrow-off_tcm23-5182.gif');
         setImage('result-header-arrow', '/virgin/Images/dropdown-arrow_tcm23-5183.gif');
         slideDown('resultspanel-content');               
      }

      this.showCalculatorPanel = showCalculatorPanel;

      function showCalculatorPanel() {
         $('calculatorPanelLink').href = "javascript:void(0);";
         $('resultsPanelLink').href = resultsPanelLink;
         slideUp('resultspanel-content');               
         setImage('result-header-arrow', '/virgin/Images/dropdown-arrow-off_tcm23-5182.gif');
         clearFieldErrors();
         slideDown('calculatorpanel-content');
         setImage('calculator-header-arrow', '/virgin/Images/dropdown-arrow_tcm23-5183.gif');
      }

      this.clearFieldErrors = clearFieldErrors;

      function clearFieldErrors() {
         $$('.fieldError').each(function(s){
               s.style.display = 'none';
         });
         $$('.topLevelFieldError').each(function(s){
            s.style.display = 'none';
         });
         $$('.fieldErrorCross').each(function(s){
            s.style.display = 'none';
         });
      }

      this.getSlideDuration = getSlideDuration;

      function getSlideDuration() {
         return slideDuration;
      }

      this.setSlideDuration = setSlideDuration;

      function setSlideDuration(duration) {
         slideDuration = duration;
      }

      this.showLoadingScreen = showLoadingScreen;

      function showLoadingScreen(elementID) {
         var element = $(elementID);
         var loadingDiv = new Element('DIV');         
         var img = imageCache['/virgin/Images/loading_tcm23-5187.gif'];
         element.parentNode.appendChild(loadingDiv);
         loadingDiv.style.height = element.getHeight() + calculatorPanelPadding + 'px';
         loadingDiv.style.top = element.offsetTop + 'px';
         loadingDiv.style.width = element.getWidth() + 'px';
         loadingDiv.style.position = 'absolute';
         loadingDiv.style.backgroundColor = '#808080';
         loadingDiv.setOpacity(loadingOpacity);
         loadingDiv.id = loadingDivId;
         loadingDiv.style.display = 'block';         
         loadingDiv.style.visibility = 'hidden';
         loadingDiv.appendChild(img);
         img.style.left = ((loadingDiv.getWidth() * 0.5) - (img.width * 0.5)) + 'px';
         img.style.top = ((loadingDiv.getHeight() * 0.5) - (img.height * 0.5)) + 'px';
         img.style.position = 'absolute';
         img.style.display = 'block';
         loadingDiv.style.visibility = 'visible';
      }

      this.removeLoadingScreen = removeLoadingScreen;

      function removeLoadingScreen() {
         $(loadingDivId).remove();
      }

      function setImage(imageID, imageSrc) {
         var image = imageCache[imageSrc];
         if (image == undefined) {
            var unknownImage = new Image();
            unknownImage.src = imageSrc;
            imageCache[imageSrc] = unknownImage;
            $(imageID).src = unknownImage.src;
         } else {
            $(imageID).src = image.src;
         }
      }

      function slideDown(elementID) {
         Effect.BlindDown(elementID, { duration: slideDuration });   
      }

      function slideUp(elementID) {
         Effect.BlindUp(elementID, { duration: slideDuration });   
      }

      function displayPanel(element) {
         element.style.display = "block";
      }

      function hidePanel(element) {
         element.style.display = "none";
      }
   }

//================================================= EFFECTS SUBSYSTEM =================================================//
}
