var Analytics = Class.create({
    subscribers : {},
    listeners : {},
    seenMemoWithTag : {},
    isEnabled: false,
    enabledModules: new Array(),
    cm_map : {},
    cm_corrected_cat : {},
    localPath : '',
    macSkipCount : 0,
    prodCatData : {},


    RPC_METHODS_ALLOWED: new Hash({
        "prodcat" : 1,
        "generic" : 1,
        "cart" : 1,
        "rpc.form" : 1,
        "search" : 1,
        "email.signup" : 1
    }),

    initialize: function(modules,enabled){
        this._addStaticListeners();
    },
    addPendingTags: function(newTags ){
        this.pendingTags = newTags;
        this.execTags();
        return this;
    },
    addElementEvents: function(newEvents){
        this.elementEvents = newEvents;
        
    },
    _addStaticListeners: function(){
        var self = this;
        document.observe("dom:loaded", function(){
            self.isEnabled = (typeof ANALYTICS_ENABLED != "undefined") ? ANALYTICS_ENABLED : false;
            self.enabledModules = (typeof ANALYTICS_MODULES != "undefined" ) ? ANALYTICS_MODULES : [];
            // console.log( "Analytics enabled: ", self.isEnabled );
            // console.log( "Analytics registered modules: ", self.enabledModules );
            self.localPath = document.location.pathname;

            // I loath this, but events fire user generated or not and something has to supress them on direct urls to SPP, for example
            if ( self.localPath.match("product") ){
                self.macSkipCount = 3; 
            }
            if (self.localPath.match("account") ){
                self.macSkipCount = 1;
            }
            if (self.localPath.match("looks") ){
                self.macSkipCount = 3;
            }
            if (self.localPath.match("artists")){
                self.macSkipCount = 1;
            }
            self.createMap();
        });


    // Mac special start
    document.observe("panelnav:show", function(event) {
     
        var open_data = event.memo.msg;
        //console.log("brand.coremetrics.panelNav.track: show / ",open_data);

        if (open_data.type === "panel"){
                   
        } else if (open_data.type === "accordion") {
        }
    });

    document.observe("accordion:open", function(event) {
        if ( self.macSkipCount ){
          self.macSkipCount--;
          return;
        } 
        var open_data = event.memo.msg;
        //console.log("brand.coremetrics.Accordion.track: open / ", open_data);
        var parentCat ='' 
        var parentCatName = '';
        var curCat = '';
        var prefix = 'MPP : ';
        if (open_data.parentId === 'globalnav_container'){
            prefix = '';
        }else{
            parentCat = open_data.parentId.match("CAT[0-9]*");
            parentCatName = self.cm_map[parentCat] + " : ";
            curCat = open_data.id.match("CAT[0-9]*")
            //console.log("CURRENT CAT ",curCat); 
            //console.log("Parent cat",parentCat,"Match ",parentCatName);
        }
        // remove Shop Products and Makeup Artistry because they are special cases 
        if (open_data.displayName != "Shop Products" && open_data.displayName != "Makeup Artistry"){
            self.addPendingTags({"CoreMetrics":{"dom:loaded":[{"params":[prefix + parentCatName + open_data.displayName,null,curCat,null,null],"tag":"cmCreatePageviewTag"}]}});
        }
    });

    // SPECIAL HOOK for Mac catalog.tmpl work around, also note, page_data doesn't have any English names so we have to use results from the RPC not in page_data, saving here.
    document.observe("panel:prodcat", function(event){
       // Save for possible later use 
           self.prodCatData = event.memo.msg.data;
    
       if ( self.macSkipCount ){
          self.macSkipCount--;
          return;
        }
       var prodcatRequest = event.memo.msg.request;
       var thisCat = '';
       if (self.cm_corrected_cat[prodcatRequest.itemId] != "undefined"){
           thisCat = self.cm_corrected_cat[prodcatRequest.itemId];
       }else{
           thisCat = prodcatRequest.itemId;
       } 
       self.addPendingTags({"CoreMetrics":{"dom:loaded":[{"params":["products : "+ prodcatRequest.parent.displayName  ,null,prodcatRequest.itemId,null,null],"tag":"cmCreatePageviewTag"}]}});
    
    });



    // this is a lot more specific to when we need a product view tag on a swatch click vs the generic swatch:click event. 
    document.observe("productmessage:cartadd/show", function(event){
        var cur_cat = event.memo.msg.path.match("CAT[0-9]*");
        var cur_prod = event.memo.msg.path.match("PROD([0-9]*)")[0];
    

    //document.observe("swatch:click", function(event){
    //   var skuname = event.memo.msg.name;
    //   var skuproduct = event.memo.msg.product;
    //skuproduct.category_id skuproduct.product_id
  
       var pdcatalog = page_data.catalog;
       var productName = '';

            if (typeof(pdcatalog) != "undefined") {
                if (typeof(pdcatalog.mpp) != "undefined") {
                    if (typeof pdcatalog.mpp.products != "undefined"){
                        for (var i=0; i < pdcatalog.mpp.products.length; i++){
                            if (pdcatalog.mpp.products[i].category_id.match(cur_cat) && pdcatalog.mpp.products[i].product_id.match(cur_prod) ){
                                //console.log("GOT NAME ",pdcatalog.mpp.products[i].cm_name, cur_cat, pdcatalog.mpp.products[i].category_id); 
                                productName = pdcatalog.mpp.products[i].cm_name;
                            } 
                        }    
                    }else{
                         Object.keys(pdcatalog.mpp).each(function(CATEGORY){    
                            var CAT = pdcatalog.mpp[CATEGORY];
                            for (var i=0; i < CAT.products.length; i++){
                                if (CAT.products[i].category_id.match(cur_cat) && CAT.products[i].product_id.match(cur_prod) ){
                                    //console.log("GOT NAME ",CAT.products[i].cm_name);
                                    productName = CAT.products[i].cm_name;
                                }
                            }
                        });
                    }
                }

            }

           self.addPendingTags({"CoreMetrics":{"dom:loaded":[{"params":[cur_prod,productName,cur_cat ,null,null,null],"tag":"cmCreateProductviewTag"}]}});
       

   });
   
    // Mac special end 

   //Search hook for frontend and soon Endeca
   document.observe("search:results", function(event){
    var res = event.memo.msg;
    self.addPendingTags({"CoreMetrics":{"dom:loaded":[{"params":[res.pageid,res.keywords,res.cat,'"' + res.count +'"',null],"tag":"cmCreatePageviewTag"}]}});
  });

        // our RPC hook
        document.observe('RPC:RESULT', function(obj){
           console.log("GOT RPC FIRE",obj); 
            var rpcRequestArray, rpcResponseArray;
            var requestMethod, requestId;
            if (typeof obj.memo.msg.request != "undefined") {
                rpcRequestArray = (obj.memo.msg.request.parameters.JSONRPC != null) ?
                    obj.memo.msg.request.parameters.JSONRPC.evalJSON() :
                    null;

                if (rpcRequestArray) {
                    rpcResponseArray = obj.memo.msg.responseText.evalJSON();
                    if (rpcResponseArray) {
                        rpcRequestArray.each(function(rpcRequest){
                            requestMethod = rpcRequest.method;
                            requestId = rpcRequest.id;
                            // console.log("Analytics handling RPC request:  ", requestMethod, " with id: ", requestId);

                            // We can do special handlers for requests here or filter out non handled requests... 
                            if (!self.RPC_METHODS_ALLOWED.get(requestMethod)) {
                                 //console.log("Analytics skipped ", requestMethod);
                            } else {
                                // Make sure we have the response for this request (id's must match).
                                var myRpcResponse = rpcResponseArray.find(function(rpcResponse){
                                    return rpcResponse.id == requestId
                                });
                                if (myRpcResponse && myRpcResponse.result != null) {
                                    //console.log("Analytics will handle ", myRpcResponse.result.data.Analytics);
                                    var newTags = myRpcResponse.result.data.Analytics;
                                    self.addPendingTags(newTags);
                                }
                            }
                        });
                    }
                }
            }
        });
    },
    addDynamicListener: function(taggingModule, myEvent, TagBlocks){
        var self = this;
        var id = "default";
        TagBlocks.each(function(tagBlock){
            if (typeof tagBlock.memo != "undefined") {
                id = tagBlock.memo;
            }
            if (!self.subscribers[id]) { self.subscribers[id] = {}; }
            if (!self.subscribers[id][taggingModule]) { self.subscribers[id][taggingModule] = {}; };
            if (!self.subscribers[id][taggingModule][myEvent]) {
                self.subscribers[id][taggingModule][myEvent] = new Array();
            } else {
                 //console.log( "Event is defined ", self.subscribers[id][taggingModule][myEvent] );
            }

            if (!self.seenMemoWithTag[id]) { self.seenMemoWithTag[id] = {}; }
            if (!self.seenMemoWithTag[id][tagBlock.tag]) {
                self.seenMemoWithTag[id][tagBlock.tag] = 1;
                self.subscribers[id][taggingModule][myEvent].push(tagBlock);
                //console.log( "pushed Event for: id: ", id, " taggingModule: ", taggingModule, " event: ", myEvent, " -> ", self.subscribers[id][taggingModule][myEvent] );
            }

        });

        // Attach the listener for this event type.
        if (!self.listeners[myEvent]) {
            self.listeners[myEvent] = 1;
            //Event.observe(window, myEvent, function(evt){
            document.observe(myEvent, function(evt){
                //console.log("running window event: ", myEvent, " with memo: ", evt.memo);

                var myId = evt.memo;
                self.enabledModules.each(function(taggingModule){
                     //console.log("for tagging module: ", taggingModule);
                    if (typeof self.subscribers[myId][taggingModule] != "undefined"){
                       if (self.subscribers[myId][taggingModule][myEvent]) {
                          self.execEventTagBlocks( self.subscribers[myId][taggingModule][myEvent] );
                       }
                    }
                });
            });
        }
    },
    execTags: function (){
        var self = this;
        if (typeof self.pendingTags == "object") {
            Object.keys(self.pendingTags).each(function(taggingModule){
                if (typeof taggingModule != "object" && self.pendingTags[taggingModule] == 'notag') {
                        return;
                }
                Object.keys(self.pendingTags[taggingModule]).each(function(myEvent){
                    // console.log("Analytics: module / event ", taggingModule, myEvent);
			        if (myEvent != 'dom:loaded'){
                        // register this event with our collection of listeners.
                        self.addDynamicListener(taggingModule, myEvent, self.pendingTags[taggingModule][myEvent]);
                        // and then execute it
                        //self.execEventTagBlocks( self.pendingTags[taggingModule][myEvent] );
                    } else {
                        // incoming tagging events under the 'dom:loaded' label can be executed straightaway.
                        self.execEventTagBlocks( self.pendingTags[taggingModule][myEvent] );
                    } 
                }); 
            });
        }
    },
    execEventTagBlocks: function(tagBlocks){
        tagBlocks.each(function(tagBlock){
            if (!tagBlock.params || !tagBlock.tag) { return; }
                 //console.log( "Analytics.execEventTagBlocks about to execute tag: ", tagBlock.tag, " with params: ", tagBlock.params );
            if (typeof window[tagBlock.tag] == "undefined") {
                 //console.log( "The Tagging Module function is not found: ", tagBlock.tag );
                return;
            }
            window[tagBlock.tag].apply(this, tagBlock.params);
        });
    },
    // Possible special funtions for front end (reserved for future use)
    onDivShow: function() {},
    onFrameUpdate: function() {},
    onJsRedirect: function() {},





// More just for Mac, but the createMap func itself or something like it could become more standard for Navs. 
createMap: function() {

    var sections = site.globalnav.config.items;
    
    for (x in sections) {
      for (y in sections[x]){
        if (y === "items"){
            var items = sections[x].items;
            for (var element = 0; element < items.length; element++){
              if (typeof(items[element].id)  != "undefined" && typeof(items[element].cmcat) != "undefined"){
                this.cm_map[items[element].id] = items[element].name;
              }
              if ( !(items[element].id.match("CAT[0-9]*")) ){
                this.cm_corrected_cat[items[element].id] = items[element].cmcat;
              }
            }
        }else{
            if (typeof(sections[x].id)  != "undefined" && typeof(sections[x].cmcat) != "undefined"){
              if ( !(sections[x].id.match("CAT[0-9]*")) ){
                    this.cm_corrected_cat[sections[x].id] = sections[x].cmcat;
                  }else{
                      this.cm_map[sections[x].id] = sections[x].name;
                  }
              }
            }
       }
    }

}




});
Analytics = new Analytics();

