/* Was this Asset loaded yet, and did the PHP Footer file find this Asset */
function does_asset_exists(filename) {
  var dfd = jQuery.Deferred();
  if ( has_loaded(filename) === true ) {
    dfd.resolve("loaded");
    return dfd.promise();
  }
  var exists = false;
  for (i = 0; i < assets_files.length; i++) {
    if (filename == assets_files[i].filename) {
      debug_print('Loading: ' + filename)
      dfd.resolve(assets_files[i].ts);
      include_once_files.push(filename);
      exists = true;
      break;
    }
  }
  if (exists === false) {
    dfd.reject("skipped");
  }
  return dfd.promise();
}

/* Helper method to apply CSS dynamicly */
function apply_css(href, version) {
  debug_print('Applying CSS to ' + href);
  $('<link rel="stylesheet" type="text/css" href="' + ajax_folder + href + version + '" />').appendTo("head");
}

/* Run main method on Class File */
function do_run_main(obj, req) {
  var dfd_run_main = jQuery.Deferred();
  if (obj['main']) {
    $.when(obj['main']()).done(function () {
      debug_print(obj.constructor.name + ' main complete');
      dfd_run_main.resolve("main_ajax_complete");
    }).fail(function(msg) {
      dfd_run_main.reject('main FN, Failed! ' + msg);
    });
  } else {
    debug_print(obj.constructor.name + " main FN not found!");
    dfd_run_main.reject('main FN not found!');
  }
  return dfd_run_main.promise();
}

/* Convert uppercase letters into underscores */
function get_tabs_name(tab_name) {
  var case_regex = /(?=[A-Z])/g; // Find Upper case
  var input = tab_name.charAt(0).toLowerCase() + tab_name.slice(1); // make first letter lowercase
  var tab = input.replace(case_regex, "_"); // replace with underscores
  var run_tab = tab.toLowerCase(); // make all lowercase
  return run_tab;
}

/* This will Run JS code for Tabs! */
function do_run(obj, req) {
  var dfd_run = jQuery.Deferred();
  var run_tab = get_tabs_name(req.params.tab);
  if (obj[run_tab]) {
    $(function() {
      $.when(obj[run_tab]()).done(function () {
        debug_print('Route: ' + obj.constructor.name + ', Tab: ' + run_tab + ' complete');
        dfd_run.resolve("fn_ajax_complete");
      }).fail(function(msg) {
        dfd_run.reject('fn_ajax Failed! ' + msg);
      });
    });
  } else if ( is_404(req.params.tab) ) {
    console.log(obj.constructor.name + ", Tab: " + req.params.tab + " FN not found!");
    do_404_page();
    dfd_run.reject('FN not found!');    
  } else {
    dfd_run.resolve("empty_page"); /* Known empty page */
  }
  return dfd_run.promise();
}

/* Just checks if file has been loaded once yet */
var include_once_files = [];
function has_loaded(file) {
  if (include_once_files.indexOf(file) === -1) {
    return false;
  } else {
    return true;
  }
}

/* JS Loader */
function load_js(scriptFile, version, obj, req, fn) {
  var method_fn = window[fn];
  var dfd_loadjs = jQuery.Deferred();
  $.getScript(ajax_folder + scriptFile + version)
          .done(function (script, textStatus) {
            $(function() {
              $.when(method_fn(obj, req)).done(function () {
                dfd_loadjs.resolve("js_complete");
              });
            });
          })
          .fail(function (jqxhr, settings, exception) {
            $(function() {
              method_fn(obj, req);
            });
            dfd_loadjs.reject('Something went wrong');
            console.warn("Something went wrong: " + exception);
          });
  return dfd_loadjs.promise();        
}

/* Does Class start_up, CSS, and JS - After main JS has completed loading... */
function do_other_function(obj, req) {
  var class_name = obj.constructor.name;
  var run_tab = "_" + get_tabs_name(req.params.tab);
  var script_file = class_name + run_tab + ".js";
  var css_file = class_name + run_tab + ".css";
  var main_css_file = class_name + "_main.css"; 
  var dfd_script = does_asset_exists(script_file);
  dfd_script.done(function (versionNumber) {
    if (versionNumber === 'loaded') {
      do_run(obj, req);
      $(function() {
        if (obj['start_up']) {
          obj['start_up']();
        }
      });
    } else {
      var dfd_other_FN = load_js(script_file, versionNumber, obj, req, 'do_run');
      $.when(dfd_other_FN).done(function () {
        $(function() {
          if (obj['start_up']) {
            obj['start_up']();
          }
        });
      }).fail(function(msg) {
        console.error(msg);
      });
    }
  }).fail(function (err) {
    do_run(obj, req);
    $(function() {
      if (obj['start_up']) {
        obj['start_up']();
      }
    });
  });
  
  var main_dfd_css = does_asset_exists(main_css_file);
  main_dfd_css.done(function (versionNumber) {
    if (versionNumber !== 'loaded') {
      apply_css(main_css_file, versionNumber);
    }
  });

  var dfd_css = does_asset_exists(css_file);
  dfd_css.done(function (versionNumber) {
    if (versionNumber !== 'loaded') {
      apply_css(css_file, versionNumber);
    }
  });  
}

/* This is the core loader for Tabs and main Route */
var cloneObject = {};
function do_tabs(class_name, req) {
  $.holdReady( true );
  
  // Re-calculate height for right body
  right_scroll();
  
  var myclass = window[class_name];
  var obj = new myclass(req);
  cloneObject = obj;
  var main_script_file = class_name + "_main.js";
  var main_dfd_script = does_asset_exists(main_script_file);
  main_dfd_script.done(function (versionNumber) {
    if (versionNumber === 'loaded') {
      var dfd_main_code = do_run_main(obj, req);
      $.when(dfd_main_code).done(function () { do_other_function(obj, req); }).fail(function(msg) {  });
    } else {
      var dfd_main_code = load_js(main_script_file, versionNumber, obj, req, 'do_run_main');
      $.when(dfd_main_code).done(function () { do_other_function(obj, req); }).fail(function(msg) { console.error(msg); });
    }
  }).fail(function (err) {
    var dfd_main_code = do_run_main(obj, req);
    $.when(dfd_main_code).done(function () { do_other_function(obj, req); }).fail(function(msg) { console.error(msg); });
  });
  
  $.holdReady( false ); // Allow DOM to load now!
  return true;
}

/* Load 404 JS for doing 404 Page */
function do_404_page() {
  var error_script_file = "page_not_found_main.js";
  var err_page = new page_not_found(false);
  if ( has_loaded(error_script_file) === true ) {
      err_page.main();
    } else {
     $.getScript(ajax_folder + error_script_file)
          .done(function (script, textStatus) {
              include_once_files.push(error_script_file);
              err_page.main();
      });
    }
}

/* Is 404 on, if so does Tab Method/File exists, if not was an exception made */
function is_404(tab_name) {
  if (do_404_page_on_bad_tabs === false) return false; /* Is 404 off?? */
  for (i = 0; i < empty_tab_pages.length; i++) {
    if (empty_tab_pages[i] == tab_name) {
      return false; /* Found allowed empty tab page */
    }
  }
  return true; /* Unable to find tab page hash in allowed list */
}