Ext.BLANK_IMAGE_URL = 'http://glink.gina.alaska.edu/cdn/latest/images/s.gif';

Ext.apply(Ext.Updater.defaults, {
  disableCaching: true
});

Ext.apply(Ext.form.VTypes, {
  'numeric': function(v) {
    var re = /^\-{0,1}\d*\.{0,1}\d*$/;
    return re.test(v);
  },

  'numericMask': /^\-{0,1}\d*\.{0,1}\d*$/,

  'numericText': 'Only numeric values are allowed',

  'integer': function(v) {
    var re = /^\-{0,1}\d+$/;
    return re.test(v);
  },

  'integerMask': /^\-{0,1}\d+$/,

  'integerText': 'Only integers are allowed'
});

Ext.Ajax.timeout = 300000

Ext.namespace('ExtApp');

ExtApp = function()
{
  return {
    content: null,
    westpanel: null,
    viewport: null,

    /**
     * Will extract the HTML content from a string, optionally can evaluate any
     * javascript that is embeded along with the content.
     *
     * @param {String} content
     * @param {Hash} params
     * @return {String} returns the content decoded/stripped of any javascript.
     */
    extract_contents: function(content, params) {
      if(!content || content.length == 0) {
        return false;
      }

      var options = { eval_scripts: true, decode: false };
      Ext.apply(options, params);

      if(options.decode) {
        content = Ext.util.Format.htmlDecode(content);
      }
      var scripts = content.extractScripts().join("\n");
      if(options.eval_scripts) {
        ExtApp.handlers.eval_javascript.call(this, scripts);
      }
      return Ext.util.Format.stripScripts(content).trim();
    },

    logger: {
      DEBUG_LEVEL: 0,
      INFO_LEVEL: 1,
      debug: function(txt) {
        if (ExtApp.log_level === ExtApp.logger.DEBUG_LEVEL) {
          console.log(txt);
        }
      }
    },
    
    init: function() {
      this.log_level = ExtApp.logger.INFO_LEVEL;
      Ext.Ajax.on('requestexception', ExtApp.handlers.exception);
    },
    
    cleanup: function() {
      Ext.Ajax.un('requestexception', ExtApp.handlers.exception);
      Ext.TaskMgr.stopAll();
    },
    
    tasks: {},
    
    set_content: function(panel) {
      this.content = panel;
    },
    
    hide_loading: function() {
      if (Ext.get('loading')) { Ext.get('loading').fadeOut(); }
      if (Ext.get('loading-mask')) { Ext.get('loading-mask').fadeOut(); }      
    },
    show_loading: function() {
      if (Ext.get('loading')) { Ext.get('loading').fadeIn(); }
      if (Ext.get('loading-mask')) { Ext.get('loading-mask').fadeIn(); }
    },
    
    load_url: function(url, params, method)
    {
      ExtApp.request(url, params, method);
    },
      
    decode_json: function(xhr) {
      var results = {};
      if (ExtApp.content_type(xhr) == 'application/json') {
        results = Ext.decode(xhr.responseText);
      }
      return results;        
    },

    xrequest: function(params) {
      if (!params) { params = {}; }
      if(params.mask === true) {
        ExtApp.page_mask.show();
      }

      Ext.applyIf(params, {
        listeners: {},
        method: 'GET',
        headers: {
          accept: "text/javascript, text/html, application/xml, text/xml, */*"
        },
        disableCaching: true
      });

      Ext.applyIf(params.listeners, {
        scope: params.scope || window
      });

      Ext.apply(params, {
        success: function(xhr, options){
          var obj = null;

          if(xhr.responseText && ExtApp.content_type(xhr) == 'text/javascript') {
            eval("obj = " + xhr.responseText);
          }
          if(options.listeners.success) {
            options.listeners.success.call(options.listeners.scope, xhr, options, obj);
          }
          if(options.listeners.complete) {
            options.listeners.complete.call(options.listeners.scope, xhr, options, obj);
          }
          if (options.mask === true) { ExtApp.page_mask.hide(); }
        },
        failure: function(xhr, options) {
          if(options.listeners.failure) {
            options.listeners.failure.call(options.listeners.scope, xhr, options, obj);
          }
          if (options.mask === true) { ExtApp.page_mask.hide(); }
        }
      });

      if (params.listeners.beforerequest && params.listeners.beforerequest.call(params.listeners.scope, params) === false) {
        return false;
      }
      
      if(params.timeout) {
        var con = new Ext.data.Connection({ timeout: params.timeout });
        return con.request(params);
      } else {
        return Ext.Ajax.request(params);
      }
    },

    /**
     * Utility function used to fetch the specified url.  Any output generated by
     * the request (if any) will be shown in a popup window.  All javascript
     * will also be evaluated.
     *  
     * @param {Hash} params
     * @param {Hash} callbacks
     * @return {Ext.Ajax.request} request
     */
    request: function(params, callbacks)
    {
      if (!params) { params = {}; }
      if(!callbacks) { callbacks = {}; }
      if(params.listeners) {
        Ext.applyIf(callbacks, params.listeners);
      }
      if(params.mask === true) {
        ExtApp.page_mask.show();
      }

      Ext.applyIf(callbacks, {
        scope: params.scope || window
      });
      Ext.applyIf(params, {
        method: 'GET',
        success: function(xhr, options){
          var results = ExtApp.decode_json(xhr);
          if (results && results.flash) {
            ExtApp.Notice.show({ msg: results.flash });
          }

          ExtApp.handlers.success.call(callbacks.scope, xhr, options, results);
          if(callbacks.success) { callbacks.success.call(callbacks.scope, xhr, options, results); }
          if(callbacks.complete) { callbacks.complete.call(callbacks.scope, xhr, options, results); }
          if (options.mask === true) {
            ExtApp.page_mask.hide();
          }
        },
        failure: function(xhr, options) {
          var results = ExtApp.decode_json(xhr);
          if (results && results.flash) {
            ExtApp.Notice.show({ msg: results.flash });
          }

          if(callbacks.failure) { callbacks.failure.call(callbacks.scope, xhr, options, results); }
          if(callbacks.complete) { callbacks.complete.call(callbacks.scope, xhr, options, results); }
          if (options.mask === true) {
            ExtApp.page_mask.hide();
          }
        },
        headers: {
          accept: "text/javascript, text/html, application/xml, text/xml, */*"
        },
        disableCaching: true
      });
      
      if (callbacks.beforerequest && callbacks.beforerequest.call(callbacks.scope, params) === false) {
        return false;
      }
      
      if(params.timeout) {
        var con = new Ext.data.Connection({ timeout: params.timeout });
        return con.request(params);        
      } else {
        return Ext.Ajax.request(params);
      }
    },
    
    submit: function(params) {
      if (!params) { params = {}; }
      Ext.applyIf(params, {
        method: 'PUT',
        headers: { 
          accept: "text/json, text/javascript, text/html, application/xml, text/xml, */*" 
        }
      });
      
      if (params.confirm) {
        Ext.Msg.confirm('Confirmation Required', params.confirm, function(but) {
          if (but == 'yes') {
            ExtApp.request(params);
          }
        });
      } else {
        ExtApp.request(params);
      }
    },
    
    /**
     * Utility function to get the location hash of the current browser window
     */
    getHash: function() {
      return window.location.hash.replace(/#/,'');
    },
    
    setHash: function(hash) {
      return (window.location.hash = hash); 
    },
    
    /**
     * Utility function used to fetch the specified url.  Any output generated
     * by the request (if any) will be showin in the main content panel replacing
     * anything that is currently shown.  All javascript will also be evaluated.
     * 
     * @param {Hash} params
     */
    update: function(params) 
    {
      var options = {
        scripts: true,
        nocache: true,
        callback: ExtApp.handlers.updaters,
        headers: { 
          accept: "text/javascript, text/html, application/xml, text/xml, */*" 
        }
      };
      Ext.apply(options, params);
      
      ExtApp.empty_panel(ExtApp.content);
      ExtApp.content.load(options);
    },

    /**
     * Utility funciton used to fetch the specified url.  Any output generated
     * by the request (if any) will be showin in the main content panel replacing
     * anything that is currently shown.  All javascript will also be evaluated.
     * 
     * @param {String} url
     * @param {Mixed} params
     * @param {String} method Http Request Method (GET/POST/DELETE/PUT)
     */
    load: function(url, params, method)
    {
      if(!params) { params = null; }
      if(!method) { method = null; }

      if(url.length === 0) { url = '/'; }
      ExtApp.update({ url: url, params: params, method: method });
    },

    /**
     * Utility function used to fetch the specified url.  Any output generated by
     * the request (if any) will be shown in a popup window.  All javascript
     * will also be evaluated.
     *  
     * @param {String} url
     * @param {Mixed} params
     * @param {String} method Http Request Method (GET/POST/DELETE/PUT)
     * @param {Hash} callbacks
     */
    go: function(url, params, method, callbacks)
    {
      ExtApp.request({ url: url, params: params, method: method}, callbacks);
    },
    
    /**
     * Refresh the current browser view.
     * 
     * @param {URL} url
     */
    refresh: function(url)
    {
      this.show_loading();
      if(!url) {
        top.window.location = unescape(window.location.pathname);
      } else {
        top.window.location = url;
      }
    },
    
    show_content_panel: function()
    {
      var content_panel = new Ext.Panel({
        region: 'center',
        id: 'content',
        contentEl: 'page-content',
        margins: '0 5 0 5',
        tbar: toolbar,
        autoScroll:false, // TODO: fix for content (login/signup/forms)
        layout: 'fit'
      });

      ExtApp.replace_content(content_panel);
    },

    /**
     * Clears the contents of the passed in Ext.Panel
     * 
     * @param {Ext.Panel} panel
     */
    empty_panel: function(panel)
    {
      if(panel && panel.items) {
        panel.items.each(function(item, index, len){
           panel.remove(item,true);
        });
      }
    },

    /**
     * Used to replace the main content panel of an ExtApp.  This will remove
     * any other content that has been loaded into the content panel.  If the main content
     * panel is a tabpanel then the active tab will be replaced.  If the panel has a card layout
     * then the active card will be replaced.
     * 
     * @param {Ext.Panel} panel
     */
    replace_content: function(panel)
    {
      if (ExtApp.content.getXType() == 'tabpanel') {
        ExtApp.replace_panel_content(panel, ExtApp.content.getActiveTab());
      } else {
        if (ExtApp.content.getLayout() == 'card') {
          ExtApp.replace_panel_content(panel, ExtApp.content.activeItem);
        } else {
          ExtApp.replace_panel_content(panel, ExtApp.content);
        }
      }
    },
    
    replace_panel_content: function(new_panel, content_panel)
    {
      ExtApp.empty_panel(content_panel);
      content_panel.add(new_panel);
      content_panel.doLayout();
    },
    
    content_type: function(xhr) {
      if (!xhr || !xhr.getResponseHeader) { return false; }
      return xhr.getResponseHeader('Content-Type').trim().split(' ')[0].replace(/;/,'');
    }
  };
}();
