var LOGIN_URL = "/moneyvillage2/log_in";
var url_base = window.location.protocol + "//" + window.location.hostname + "/Moneyudoo/php/moneyudoo/"; // this will be stripped when comparing URLs
var forms_service_url = "/Moneyudoo/foo/start/";
var creditors_service_url = "/Moneyudoo/creditors/form/";
var letter_service_url = "/Moneyudoo/initial_letter/form/";
var income_boosting_url = "/Moneyudoo/income_boosting/form/";
var spending_slasher_url = "/Moneyudoo/spending_slasher/form/";
var spending_tracker_url = "/Moneyudoo/spending_tracker/form/";
var homepage_url = "/Moneyudoo/php/moneyudoo/";
var total_pages = 163; // change to reflect real total
var skip_login = /deckchair/.test(document.location.href);
var specify_fields = false; // XXX an idea for optimisation, if needed

function normaliseURL(url) {
    // we consider a match on "sub" pages, i.e. page1-2-5 is considered
    // the same as page1-2
    // we also strip out the base relative to which all pages live
    url = url.replace(url_base, "");
    return url;
}

// shortcut
function L(x) {
   if (window.console && window.console.log)
     window.console.log(x);
}

function format_amount(i) {
   if(isNaN(i)) { i = 0.00; }
   var minus = '';
   if(i < 0) { minus = '-'; }
   i = Math.abs(i);
   i = parseInt((i + .005) * 100);
   i = i / 100;
   s = new String(i);
   if(s.indexOf('.') < 0) { s += '.00'; }
   if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
   s = minus + s;
   return s;
}

function pounds_or_euros(i) {
   var currency = document.location.href.match(/ie/) ? '&euro;' : '&pound;'; 
   return currency + format_amount(i);
}


function __getWebserviceURL(table_id) {
    if (table_id == 'diypack_user_creditors') {
        return creditors_service_url;
    } else if (table_id == 'diypack_initial_letter') {
        return letter_service_url;
    } else if (table_id == 'diypack_income_boosting') {
        return income_boosting_url;
    } else if (table_id == 'diypack_spending_slasher') {
        return spending_slasher_url;
    } else if (table_id == 'diypack_spending_tracker' || table_id == 'diypack_spending_tracker_dates') {
        return spending_tracker_url;
    } else {
        return forms_service_url;
    }
    return web_service_url;
}

function __getFieldsFromForm(form_obj) {
    input_fields = $.makeArray(form_obj.map(function() {
		return $.makeArray(this.elements);
	    })
	.map(function () {
		if(this.name != "")
		    return this.name;
	    })
	);
    done = {}
    ret = []
    for (x=0; x<input_fields.length; x++) {
	val = input_fields[x]
	if (!done[val]) {
	    done[val] = true;
	    ret.push(val);
	}
    }
    return ret
}

/* return the jQuery input element */
function __find_input(key, form_obj) {
   var inp = $('[name="' + key +'"]', form_obj);
   if (!inp.size())
     inp = $('#' + key, form_obj);
   if (!inp.size())
     inp = $('#id_' + key, form_obj);
   return inp;
}

function __prefill_form(form_obj, key, value) {
   // look for it by name
   var inp = __find_input(key, form_obj);
   if (!inp.size()) {
      return;
   }
   if (inp.attr('type')=='checkbox') {
     if (value) inp.attr('checked', 'checked');
     else inp.removeAttr('checked');
   } else if (inp.attr('type')=='radio') {
      var _one_radio_checked = false;
      inp.each(function(i) {
        var v = $(this).val();
        if (v==value || (value==1 && v=='true') || (value==0 && v=='false')) {
          this.checked = true;
          _one_radio_checked = true;
        } else this.checked = false;
      });
      if (!_one_radio_checked && value) {
         // value is available but no found radio value that this can check
	  L("Found a value which I can't use on a radio button ("+key+")");
      }
   } else if (inp[0].tagName == 'SELECT') {
      $('option', inp).each(function(i) {
         var v = $(this).val();
         if (v==value || (value==1 && v=='true') || (value==0 && v=='false')) {
	    if (key != 'creditor') // doesn't work in IE6
	      $(this).attr('selected', 'selected');
	 }
      });
   } else 
     if (value !== null)
       inp.val(value);
   
   // comment!
   $('span.view__'+key, form_obj).text(value);
}

function __click_deletebyid(element) {
   var jelement = $(element);
   var id = $('input[name="id"]', jelement.parents('.replicated')).val();
   $.getJSON(forms_service_url + 'deleteSavedData',
             {id:id, table:jelement.parents('form').attr('id')});
   jelement.parents('.replicated').remove();
   return false;
}

function __find_replicate_container(form_obj) {
   if ($('#replicate__' + form_obj.attr('id')).size()) {
      return $('#replicate__' + form_obj.attr('id'));
   }
   else if ($('#replicate').size())
     return $('#replicate');
   return null;
}

function __prefill_multi_form(form_obj, key, values, index) {
   // create or use existing container?
   var container;
     
   var copies_container;
   if ($('#copies__' + form_obj.attr('id')).size())
     copies_container = $('#copies__' + form_obj.attr('id'));
   else if ($('#copies').size())
     copies_container = $('#copies');
     
   if ($('#replicated__'+ form_obj.attr('id') +'-' + index).size()) {
      container = $('#replicated__'+ form_obj.attr('id') +'-' + index);
   
   } else {
      var replicate = __find_replicate_container(form_obj);
      if (replicate.size() != 1)
        alert("error no replicate for this form object");
      container = replicate.clone();
      container.attr('id', 'replicated__'+ form_obj.attr('id') +'-' + index).addClass('replicated');
      copies_container.append(container);
   }
   if (key != '__multi__')
     __prefill_form(container, key, values[index]);

   // add a delete link
   if ($('input[name="id"]', container).size()==1) {
      if ($('a.deletebyid', container).size()) {
         $('a.deletebyid', container).click(function() {
	    return __click_deletebyid(this);
	 });
      }
   }
     
}

function __prefill_choices(form_obj, choices) {
   $.each(choices, function(key, values) {
      var inp = __find_input(key, form_obj);
      if (!inp.size()) {
         L("No options called '" + key); // remove on going live
      } else {
         $.each(values, function(i, value) {
            inp.append($('<option></option>').val(value[0]).text(value[1]));
         });
      }
   });
}

function __show_input_error(inp, message) {
   inp.addClass('error');
   var msg_id = _gen_element_id('msg');
   inp.after($('<span></span>').text(message).addClass('error').attr('id', msg_id));
   inp.bind('change', function() {
      $(this).removeClass('error');
      setTimeout(function() {
        $('#'+msg_id+ ':visible').hide();
      }, 1*1000);

   });
}

function __show_validation_error(key, message) {
   var _container = $('#content');
   if (!_container.size())
     _container = $('form');
   var inp = __find_input(key, _container);
   if (!inp.size()) {
      L("No input called '" + key + "' which is fine I guess"); // remove on going live
      return;
   }
   __show_input_error(inp, message);
}

function __show_multi_validation_error(key, message, index) {
   container = $('#replicated-' + index);
   if (!container.size()) 
     container = $('.new');
   if (!container.size()) {
      // fall back on stupid one
      __show_validation_error(key, message);
      return
   }
   
   var inp = __find_input(key, container);
   if (!inp.size()) {
      L("No input called '" + key + "' which is fine I guess"); // remove on going live
      return;
   }
   __show_input_error(inp, message);
   
}

_gen_element_id = function(prefix) {
  return prefix + '__' + (Math.random()+'').substring(2, 10);
};

function __show_message(message, type) {
   var msg_id = _gen_element_id('msg');
   var _container = $('#content');
   if (!_container.size())
     _container = $('form');
   _container.append($('<div class="savemessage"></div>').attr('id', msg_id).addClass(type).text(message));
   setTimeout(function() {
      $('#' + msg_id).hide(300);
   }, 10*1000);

}

function __show_error_message(message) {
   return __show_message(message, "error");
}

function __show_success_message(message) {
   return __show_message(message, "success");
}



function __process_save_submission(res) {
   // remove all previous old messages
   $('.savemessage').remove();
   $('span.error').remove();
   
   if (res.error)
     __show_error_message(res.error);
   if (res.validation_errors) {
      if (res.__multi__) {
         $.each(res.validation_errors, function(indexed_key, message) {
            var index = parseInt(indexed_key.match(/--(\d+)/)[1]);
            var key = indexed_key.replace(/--\d+/g, '');
            __show_multi_validation_error(key, message, index);
         });
      } else {
         $.each(res.validation_errors, function(key, message) {
            __show_validation_error(key, message);
         });
      }
   }
   // if there were no errors and the table has a class "reload"
   // then reload the whole page
   // onclick="window.location.reload(true)"
   if ($('form.reload').size() && res.success) {
      // but this can't be in the async so chop it of with a timer
      setTimeout(function() {
         window.location.reload(true);
      }, 100);
   } else if ($('form.generatepdf').size() && res.success) {
      // but we don't want this to happen too soon to avoid conflicts
      start_getGeneratedPDF($('form.generatepdf').attr('id'));
   } else if (typeof post_Save_callback != "undefined") {
      post_Save_callback(res);
   }
  
}


/* This method solves the inherent problem of checkboxes that 
    unchecked they are not sent at all. This is usally not a big problem
   because you can like absence to the same as being false.
   However, if you have form that looks like this:
     Name: _Peter___
     Gay: [ ]
     Name: _Norton__
     Gay: [x]
     Name: _Seb_____
     Gay: [ ]
   And then submit that form, what you'll get serverside is this:
     Name = ['Peter','Norton','Seb']
     Gay: [true]
   We solve that here by inserting a hidden form by the same name
   and value 'false' when checkboxes are unchecked.
 */
function __smart_checkbox_toggle(checkbox_element) {
   if (checkbox_element.checked) {
      var container = $(checkbox_element).parent();
      var name = $(checkbox_element).attr('name');
      $('input[type="hidden"]', container).each(function(i, e) {
         if ($(e).attr('name')==name) 
           $(e).remove();
      });
   } else {
      $(checkbox_element).after($('<input type="hidden" value="false"/>')
                                .attr('name', $(checkbox_element).attr('name')));
   }
}

/* Validators */
function __validation_error(inp, msg) {
   inp.addClass('error').bind('focus', function() { 
      $(this).removeClass('error'); 
   });
   alert(msg);
   return false;
}

/* A good candidate that might be worth installing is
 * http://webcoder.info/downloads/validate.html */
function validate__ukpostcode(inp) {
   var v = inp.val();
   if (v && $.trim(v)) {
      v = $.trim(v.toUpperCase());
      
      // if the postcode lacks a space before the last number, add it
      // 'WC2H 8DN' <--- works, 'WC2H8DN' <--- doesn't :(
      if (!v.match(/ /))
	// 'E16JX' --> 'E1 6JX'
	v = v.replace(/([0-9][ABD-HJLNP-UW-Z]{2})$/, ' $1');
      
      if (!v.match(/GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2}/))
	return __validation_error(inp, "Not a valid UK postcode");
   }
   return true;
}

function validate__float(inp) {
   if (inp.val()) 
     if (!/^((\d+(\.\d*)?)|(\-\d+(\.\d*)?)|((\d*\.)?\d+))$/.test(inp.val()))
       return __validation_error(inp, "Not a valid number");
   return true;
}

function validate__int(inp) {
   if (inp.val()) 
     if (/[^\d]/.test(inp.val()))
       return __validation_error(inp, "Not a valid integer number");
   return true;
}

function validate__isodate(inp) {
   if (inp.val())
     if (!/\d{4}\/\d{2}\/\d{2}/.test(inp.val()))
       return __validation_error(inp, "Not a valid ISO date");
   return true;
}

function validate__notblank(inp) {
   if (inp.val())
     return true;
   return __validation_error(inp, "Input blank");
}

function __before_ajaxSubmit(form_data, form_obj) {
   var errors = 0;
   $('input[class*=validate__]', form_obj).each(function() {
      var inp_obj = $(this);
      if (inp_obj.hasClass('validate__ukpostcode'))
	if (!validate__ukpostcode(inp_obj))
	  errors++;
      if (inp_obj.hasClass('validate__float')) 
	if (!validate__float(inp_obj)) 
	  errors++;
      if (inp_obj.hasClass('validate__int'))
	if (!validate__int(inp_obj)) 
	  errors++;      
      if (inp_obj.hasClass('validate__isodate'))
	if (!validate__isodate(inp_obj))
	  errors++;
   });
   $('input.validate__notblank:visible').each(function() {
      if (!validate__notblank($(this)))
        errors++;
   });
   return !errors;
}


function __load_nav() {
   
   $.getJSON(forms_service_url + 'getSavedData', {tables:'diypack_visited_urls'}, function(res) {
      // normalise url(s) so it's always an array
      var saved_urls = $.makeArray(res.url);
      // build progress bar
      var progress_bar = $('#progress-fill img');
      var progress_percent = parseInt((saved_urls.length / total_pages)* 100);
      var progress = parseInt((saved_urls.length / total_pages) * progress_bar.width());
      progress_bar.css("position", "absolute");
      progress_bar.css("clip", "rect(0px "+progress+"px 20px 0px)");
      $('span#progress-percent').text(progress_percent);
      // add current page to stored list of visited pages
      var current_url = normaliseURL(document.location.href);
      if (jQuery.inArray(current_url, saved_urls) == -1)
        // to avoid conflict errors, delay this one
        setTimeout(function() {
           $.getJSON(forms_service_url + 'RememberProgress', {url:normaliseURL(document.location.href)});
        }, 500);
      
      //visit each link in left nav and decorate it depending on visited status
      $('li[class*="leftnav"]', $('#navigation')).each(function() {
         //var n = 0;
         var has_visited = false;
         var link = $(this).children()[0];
         var link_url = normaliseURL($(link).attr('href'));
         if (jQuery.inArray(link_url, saved_urls) > -1) {
            has_visited = true;
         }
         if (link_url == current_url) {
            $(this).attr('class', 'sidenav green');
         } else if (has_visited) {
            $(this).attr('class', 'sidenav visited');
         } else {
            $(link).removeAttr('href');
            $(this).attr('class', 'sidenav disabled');
         }
      });

   });
   
}


var _progress_urls = {};

var datepicker_options = {firstDay: 1, dateFormat: 'dd/mm/yy'};

var when_logged_in = function() {
   // Before anything else, check that the user is logged in
   // 
    function submit_options(service_url) {
        data = {
             url: service_url + 'Save',
             type: 'POST',
             dataType: 'json',
             beforeSubmit: __before_ajaxSubmit,
             success: __process_save_submission
        }
        return data
    };
   var _forms = $('form.crud');
   var _forms_size = _forms.size(); // needed to be able to post_getSavedData_callback in last .getJSON
   _forms.submit(function() {
      // work out a web service to post to, depending on 
      // the form id
      var web_service_url = __getWebserviceURL($(this).attr('id'));
      $(this).ajaxSubmit(submit_options(web_service_url));
      return false;
   }).each(function(i) {
      var form_obj = $(this);
      var web_service_url = __getWebserviceURL(form_obj.attr('id'));

      // ensure we are saving to the specified table
      form_obj.append($('<input type="hidden" name="tables" />')
                      .attr('value', $(this).attr('id')));

      if (specify_fields) {
         input_fields = __getFieldsFromForm(form_obj);
         var query = {tables:form_obj.attr('id'), fields:input_fields};
      } else {
         if (form_obj.attr('class').search('byidonly') > -1)
           var query = {tables:form_obj.attr('id')};
         else
           var query = {};
      }
      $.getJSON(web_service_url + 'getSavedData?_='+Math.random(), query, function(res) {
         if (res.__choices__) {
            __prefill_choices(form_obj, res.__choices__);
         }
         
         if (!res.__multi__) {
            // If there are any checkbox inputs, add a hidden one that indicates that
            // the checkbox was offered. We can then use this infer that certain
            // checkboxes could have been true.
            $('input[type="checkbox"]', form_obj).each(function() {
               form_obj.append($('<input type="hidden" value="0"/>')
                               .attr('name', $(this).attr('name')+'__checkbox'));
            });            
         }
         
         var replicate = __find_replicate_container(form_obj);
         
         $.each(res, function(key, item) {
            if (res.error) {
              __show_error_message(res.error);
            }
            if (jQuery.inArray(form_obj.attr('id'), res.__multi__) > -1) {
               if (replicate===null) {
                   L("DOM must contain exactly one node with id 'replicate' or 'replicate__<id of form>'");
                } else {
                   $.each(item, function(i) {
                      __prefill_multi_form(form_obj, key, item, i);
                   });

                }
            } else if (key == '__choices__' || key == '__multi__') {
                // skip. It's been done before the $.each loop
            } else {
                __prefill_form(form_obj, key, item);
            }
         });
         
	 if ($('input.datepicker').size()) {
	    if (form_obj)
	      $('input.datepicker', form_obj).datepicker(datepicker_options);
	    else
	      $('input.datepicker').datepicker(datepicker_options);
	 }
	    
         if (replicate) {
            replicate.remove();
         }
         
         // Prepare "smart checkboxes". I.e. unchecking a checkbox
         // adds a hidden input that looks like this: 
         // <input name="nameofcheckbox" value="false" type="hidden">
         if (res.__multi__) {
            $.each(res.__multi__, function(i, form_id) {
               var form_obj = $('#' + form_id);
               $('input[type="checkbox"]', form_obj).change(function() {
                  __smart_checkbox_toggle(this)
               });
               // that sets an event for changing checkboxes
               // but what about those already set?
               $('input[type="checkbox"]', form_obj)
                 .each(function() {
                    if (!this.checked)
                      $(this).after($('<input type="hidden" value="false"/>')
                                    .attr('name', $(this).attr('name')));
                 })
               
            });
         }
         
         // Hack to prevent Firefox from being clever and setting values to 
         // input fields based on previous DOM loading. This is not necessary
         // if you Shift+Refresh because then it won't prefill the form
         $('.new input[name="id"]').val('');
         
         if (i==_forms_size-1) {
           // then this is the last success function of the
           // forms.getJSON()s
           if (typeof post_getSavedData_callback != "undefined") {
             post_getSavedData_callback();
           }
         }
      });
   });
   
   // Because the nav is "less important" than the forms we delay loading
   // it for half a second.
   setTimeout(function() {
      __load_nav();
   }, 500);
};


function __get_login_url() {
   var url = LOGIN_URL;
   if (url.substring(0,1)=='/') url = window.location.href.split('/').slice(0, 3).join('/') + url;
   url += '?came_from=' + encodeURI(window.location.href);
   return url;
}

function __update_myaccount_box(fullname) {
   $('#userbox-myaccount').show().prepend($('<span></span>').text("Welcome " + fullname));
   $('#userbox-login').hide();
   
}
				

var logged_in = false;
var paid_access = false;

$(function() {
   // Before doing anything else check that the user is logged.
   // If logged in, execute when_logged_in() (which used to be the old $(function(){...})
   // If not do a Javascript redirect 
   if (!skip_login) {
      if (document.location.pathname == homepage_url || document.location.pathname == homepage_url+"index.php") {
	 $.ajax({
	    url: forms_service_url + 'isLoggedIn_json',
	      cache: false,
	      dataType: "json",
	      success: function(res) {
		 logged_in = res.logged_in;
		 paid_access = res.paid_access;
		 if (res.logged_in) {
                    if (res.fullname)
                      __update_myaccount_box(res.fullname);
		    $('#loggedincontinue').show();
		    $('div#login').hide();
		    $('div#signup').hide();
		 }
	      }
	 });	 
      } else {
	 $.ajax({
	    //url: forms_service_url + 'isLoggedIn_json?came_from=' + window.location.href,
	    url: forms_service_url + 'getAllowedURL_json?current_url=' + window.location.href,
	      cache: false,
	      dataType: "json",
	      success: function(res) {
		 logged_in = res.logged_in;
		 paid_access = res.paid_access;
		 if (res.redirect_url) {
		    setTimeout(function() {
		       window.location.href = res.redirect_url;
		       //alert(res.redirect_url);
		    }, 300);
		 } else if (res.logged_in) {
                    if (res.fullname)
                      __update_myaccount_box(res.fullname);
		    when_logged_in();
		 } else alert("Not logged in");
	      }
	 });
      }
   } else {
      when_logged_in();
   }
});
