var mochilaSuperWidget = function(inlineParams,inlineDefaultParams) {
    
    /********************* ULTILITY FUNCTIONS *************************/

    // this is the basic template replacement function, replaces tokens in the form of #{foo}
    // it takes an optional 3rd parameter, subFuc - to programatically determine the value
    
    var mochilaEval = function(template,params,subFunc) {
        var subFunc = subFunc || function() {};
        var match;var compiled = [];
        while (template.length > 0) {
            if (match = template.match(/(^|.|\r|\n)(#\{(.*?)\})/)) {
                compiled.push(template.slice(0, match.index));
                compiled.push(match[1] || '');
                var list = match[3].split(/\.|\[|\]\[|\]\.|\]/);
                if (!list[list.length-1]) list.pop();
                if (!params[list]) {compiled.push(subFunc(list));}
                else{compiled.push(params[list]);
            }
                template = template.slice(match.index + match[0].length);
            } else {
                compiled.push(template), template = '';
            }
        }
        return compiled.join("");
    }
    
    //this takes a destination and souce object and copies properties over
    var extendObj = function(destination, source) {
      for (var property in source) 
        destination[property] = source[property];
      return destination;
    };
    
    // this function takes a series of objects and merges their properties. in the order of highest priority last.
    var union = function() {
        var finalObj = {};
        for (var i=0; i < arguments.length; i++) 
            extendObj(finalObj,arguments[i]);
        return finalObj;
    };
    
    // looks in the window's URL and looks for a key = value pair and returns the value, or '' if its not there
    var gup = function( name ) {
        var results = (new RegExp("[\\?&]"+name+"=([^&#]*)")).exec(window.location.href);
        return ( results == null )?'':results[1];
    };
    
    // takes a params object and returns a query string
    var toQueryString = function(queryObj) {
        var params=[];
        for (var property in queryObj)
            params.push(property+'='+queryObj[property]);
        return params.join('&');
    };
    var log = function() {
        if (typeof console !='undefined'){
            console.log(arguments);
        }
    };
    
    /********************* END ULTILITY FUNCTIONS *************************/
    
    
    
    /********************* LOGIC FOR LOADING A SUPERWIDGET *************************/
    /*
         
         objects (in order of priority)
         
         inlineParams        -> the main params object
         URLParams           -> the params detected in the URL
         inlineDefaultParams -> a 2nd object passed to this function
         defaultsObj         -> a hard coded object in this file
         
    1. takes the union of these 4 objects to determine the correct param set.
    2. determines if an article was requested
    3. makes a script tag request to the correct url
         
    
    */
    
    var defaultsObj = {
                    // these are defaults param object. these will (and should) get overwritten
                    
                    'buyerId'          :'SnapTimesDEFAULT',
                    'buid'             :'',
                    'channelId'        :'',
                    'destination'      :'',
                    'templateId'       :'',
                    'assetId'          :'',
                    'articleId'        :'',
                    'assetClass'       :'',
                    'badgeTemplateId'  :'',
                    'toutSection'      :'',
                    'toutPosition'     :'',
                    'articleTemplateId':'',
                    'widgetClass'      :'',
                    'issueDate'        :'' /* Nat Geo */
                };
                
    // figures out the master param set, which parameters to look in the URL for, which is the union of the 3 other objects
                
    var masterParamSet = union(defaultsObj,inlineDefaultParams,inlineParams);            
    
    // this function looks for params in the URL, if found, puts them in the URLParams object
    
    var URLParams = function() {
        var found = {};
        for (var property in masterParamSet){
            var result = gup(property);
            if (result!='') found[property]=result;
        };
        return found;
    };
    
    // in order of least to greatest priority
    
    var paramsObj = union(
                            defaultsObj,         // hard coded defaults Obj
                            inlineDefaultParams, // passed in defaults obj
                            URLParams(),           // params detected in URL
                            inlineParams         // params defined in snippet
                        );
                        
        // log('defaultsObj        ',defaultsObj        );
        // log('inlineDefaultParams',inlineDefaultParams);
        // log('URLParams()        ',URLParams()        );
        // log('inlineParams       ',inlineParams       );
        
    

    //determines which type of widget was requested
    
    var requestedWidget = function() {
        
        if (paramsObj.requestedWidget=='mochilaAd') {
            return 'mochilaAd';
        }
        else if (gup('articleId')!='' || gup('assetId')!='') {
            return 'article';
        }
        else if(paramsObj.requestedWidget=='compositeWidget'){
            return 'compositeWidget';
        }
        else if (paramsObj.requestedWidget == 'tout') {
            return 'tout';
        }
        else{
            return 'compositeWidget';
        }
    };
    
    
    if (requestedWidget()=='compositeWidget') {
        
        // composite widgets have channel ids defined server side.
        delete paramsObj.channelId;
        
        var evalParams = {
            queryParams : toQueryString(paramsObj),
            server      : 'http://admatch-syndication.mochila.com',
            view        : '/public/widget/compositeWidget.xrap?'
        }; 

    } else if (requestedWidget() == 'article'){
        // correct parameter naming
        paramsObj.badgeDestId = paramsObj.destination;
        paramsObj.assetId     = paramsObj.articleId;
        
        var evalParams = { 
            queryParams     : toQueryString(paramsObj),  
            server          : 'http://admatch-syndication.mochila.com',
            view            : '/public/article/compositeWidgetArticle.xrap?'
        };
        if(gup('articleTemplateId').substr(0,6) == 'natGeo') {
          evalParams = { 
              queryParams     : toQueryString(paramsObj),  
              server          : 'http://admatch-syndication.mochila.com',
              view            : '/public/widget/compositeWidgetNatGeo.xrap?'
          };
        }
        
    } else if (requestedWidget() == 'tout'){
        
        // correct parameter naming
        paramsObj.badgeDestId = paramsObj.destination;
        paramsObj.assetId     = paramsObj.articleId;
        
        var evalParams = { 
            queryParams     : toQueryString(paramsObj),  
            server          : 'http://admatch-syndication.mochila.com',
            view            : '/public/widget/compositeWidgetTout.xrap?'
        };
        
    } else if(requestedWidget()=='mochilaAd'){
        
        paramsObj.assetId     = paramsObj.articleId;
        
        var evalParams = { 
            queryParams     : toQueryString(paramsObj),  
            server      : 'http://admatch-syndication.mochila.com',
            view            : '/public/ad/renderAd.xrap?'
        };
    };
    
    document.write(
        mochilaEval('<script src="#{server}#{view}#{queryParams}&stdout=yes&renderMimeType=javascript"></script>',evalParams)
    );
};

var mochilaSuperWidgetAd = function(obj) {
    var gup = function( name ) {
        var results = (new RegExp("[\\?&]"+name+"=([^&#]*)")).exec(window.location.href);
        return ( results == null )?'':results[1];
    };
    document.write('<script src="http://admatch-syndication.mochila.com/public/ad/renderAd.xrap?buyerId=' + obj.buyerId + '&adPos=' + obj.adPos + '&widgetClass=' + gup('widgetClass') + '&stdout=yes&renderMimeType=javascript"><\/script>');
}
