/* javascript to support overriding coveo styles */

$(document).ready(function() {
	console.log('C40 $(document).ready');	
    if (C40CommunityStyles.checkLocation(['[/]s[/]profile', '[/]s[/]my-discussions', '[/]s[/]my-hub'])) {
	    C40CommunityStyles.init();
    }
    if (C40CommunityStyles.checkLocation(['[/]s[/]global-search'])) {
	    C40CoveoOverride.init();
    }
});

var C40CommunityStyles = {
    debug:false,//XXX set this to true to get more console logs
    checkLocation: function(containsArray) {
        var loc = document.location.href;
        for (var i = 0; i < containsArray.length; i++) {
            if (loc.match(containsArray[i])) { return true;} 
        }
        return false;
    },
    initPollingInterval: -1,	//used as a unique identifier for setinterval and clearinterval 
    initPollingIndex: -1,		//used to force a runaway setinterval to stop
    maxseconds:20,
    init: function () {
        console.log('C40CommunityStyles.init()'); 
		//XXX Things take a while to load in SF. we have to poll until the messages have loaded. Then we can update them.
		C40CommunityStyles.initPollingIndex=0;
		C40CommunityStyles.initPollingInterval = window.setInterval(C40CommunityStyles.initPolling, 1000);

    },
    initPolling: function() {
    	if (C40CommunityStyles.debug) { console.log('C40CommunityStyles.initPolling(): '+C40CommunityStyles.initPollingIndex);}
		if (C40CommunityStyles.readyToGo()) {
			window.clearInterval(C40CommunityStyles.initPollingInterval);
			C40CommunityStyles.override();	
		}
		else if (C40CommunityStyles.initPollingIndex++ > C40CommunityStyles.maxseconds) {//give up after 20 seconds
			if (C40CommunityStyles.debug) { console.log('C40CommunityStyles could not initialize');}
			window.clearInterval(C40CommunityStyles.initPollingInterval);
		}
    },
    readyToGo: function() { //is everything we need ready?
		if (C40CommunityStyles.debug) { console.log('C40CommunityStyles.readyToGo()');}
        return ($(':contains("This filter begs your pardon")').length > 0) ||
               ($(':contains("Follow the leaders")').length > 0);
    },
	override : function() { //make style overrides
		if (C40CommunityStyles.debug) { console.log('C40CommunityStyles.override()');}
		C40CommunityStyles.changeEmptyErrorMessage();
        C40CommunityStyles.registerFilterEvents();
	},
	errorOtherUserNoContentTitle: '<span class="c40-override-emptyresult-message">This user has not joined a conversation yet.<span>',
	errorOtherUserNoContentDetail: '<span class="c40-override-emptyresult-detail">&nbsp;</span>',
	errorCurrentUserNoContentTitle: '<span class="c40-override-emptyresult-message">You have not posted a comment or question yet.<span>',
	errorCurrentUserNoContentDetail: '<span class="c40-override-emptyresult-detail">Visit the <a href="/s/all-discussions">All Discussions</a> page to join the conversation.</span>',
	errorMyHubNoContentTitle: '<span class="c40-override-emptyresult-message">You have not posted a comment or question yet.<span>',
	errorMyHubNoContentDetail: '<span class="c40-override-emptyresult-detail">Use the ask a question button to start a conversation.</span>',
	errorMyDiscNoContentDetail: '<span class="c40-override-emptyresult-detail">Visit the <a href="/s/all-discussions">All Discussions</a> page or use the ask a question button to join the conversation.</span>',
	changeEmptyErrorMessage: function() {
		if (C40CommunityStyles.debug) { console.log('C40CommunityStyles.changeEmptyErrorMessage()');}
		var emptyErrorMessageTitle = C40CommunityStyles.errorOtherUserNoContentTitle;
		var emptyErrorMessageDetail = C40CommunityStyles.errorOtherUserNoContentDetail;
        if (C40CommunityStyles.isMyDiscussion()) {
			emptyErrorMessageTitle = C40CommunityStyles.errorCurrentUserNoContentTitle;
			emptyErrorMessageDetail = C40CommunityStyles.errorMyDiscNoContentDetail;
        }
		else if (C40CommunityStyles.isMyProfile()) { 
			emptyErrorMessageTitle = C40CommunityStyles.errorCurrentUserNoContentTitle;
			emptyErrorMessageDetail = C40CommunityStyles.errorCurrentUserNoContentDetail;
		}
        //profiles and my discussions
        var emptycss = '[feeds_placeholding-emptyfeed_emptyfeed] ';
		var el = $(emptycss + 'h3:contains("This filter begs your pardon")');
		C40CommunityStyles.changeErrorAndSiblings(el, emptyErrorMessageTitle,emptyErrorMessageDetail);
        //my discussions - all updates
		el = $(emptycss +'h3:contains("Follow the leaders")');
		C40CommunityStyles.changeErrorAndSiblings(el, emptyErrorMessageTitle,emptyErrorMessageDetail);
        //my hub - peer sharing
		el = $('.noFeedItems .noFeedTitle');
		C40CommunityStyles.changeErrorAndSiblings(el, C40CommunityStyles.errorMyHubNoContentTitle,C40CommunityStyles.errorMyHubNoContentDetail);
        
	}, //el=element with error to change, title=new title string, detail = new detail string
	changeErrorAndSiblings: function(el, title, detail) {	
		el.html(title);
		$(el.siblings()[0]).html(detail);
	},
    isMyProfile: function() {
        //XXX profile Editable = my profile? if this isn't good enough, put the user profile id as data in the my profile menu link and compare with document.location.href
        return ($('.forceActionLink[title="Edit"]').length > 0);
    },
    isMyDiscussion: function() { 
        return (document.location.href.endsWith('/s/my-discussions'));
    },
    isMyHub: function() {
        return document.location.href.match('[/]s[/]my-hub');
    }, 
    isProfile: function() {
        return document.location.href.match('[/]s[/]profile[/]');
    }, 
    registerFilterEvents: function() {
		if (C40CommunityStyles.debug) { console.log('C40CommunityStyles.registerFilterEvents()');}
        if (C40CommunityStyles.isMyHub()) {
    		if (C40CommunityStyles.debug) { console.log('C40CommunityStyles isMyHub'); }
            var targetNode = $('.forceChatterCompactFeed.compactFeed')[0];
            C40CommunityStyles.filterObserveChanges(targetNode);
        }
        else if (C40CommunityStyles.isProfile()) {
    		if (C40CommunityStyles.debug) { console.log('isProfile: register event'); }

            var targetNode = $('.userFeed')[0]; //it has to be a parent high enough up the DOM that it itself doesn't get removed
            C40CommunityStyles.filterObserveChanges(targetNode);
        }
    },
    filterObserveChanges: function(targetNode) {
       //targetNode needs to be a parent that is unlikely to be removed itself
       //set up mutation observer for that section
       //https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
       var config = { attributes: false, childList: true, subtree: true };
       var callback = function() {
           if (C40CommunityStyles.debug) { console.log('mutation observed for outer container triggered');}
           //XXX wait for message to finish changing before trying to overwrite it. 
	        C40CommunityStyles.pollForFilterTriggeredEvent(); 
       };
       var observer = new MutationObserver(callback);
       observer.observe(targetNode, config); 
       C40CommunityStyles.filterPollingObserver = observer; //save for later
    },
    filterPollingObserver: null,//so we can disconnect the observer when needed
    filterPollingInterval: -1,	//used as a unique identifier for setinterval and clearinterval 
    filterPollingIndex: -1,		//used to force a runaway setinterval to stop
    filterPollingFrequency: 1000,//one sec (note: tried 250, but this increases chance of missing Edit button for distinguishing between my profile and other profile and isn't appreciably faster for the loading timeframe)
    pollForFilterTriggeredEvent: function() {
		if (C40CommunityStyles.debug) { console.log('C40CommunistStyles.pollForFilterTriggeredEvent()');}
        $('.noFeedItems').addClass('c40hide'); //hide my hub container where message will change
		C40CommunityStyles.filterPollingIndex=0;
		C40CommunityStyles.filterPollingInterval = window.setInterval(C40CommunityStyles.filterPolling, C40CommunityStyles.filterPollingFrequency);
        C40CommunityStyles.filterPollingObserver.disconnect();//stop observing or filter loop never ends
    },
    filterPolling: function() {
    	if (C40CommunityStyles.debug) { console.log('C40CommunityStyles.filterPolling(): '+C40CommunityStyles.filterPollingIndex);}
        var ready = ($(':contains("This filter begs your pardon")').length > 0);
		if (ready) {
			window.clearInterval(C40CommunityStyles.filterPollingInterval);
		    C40CommunityStyles.changeEmptyErrorMessage();
            $('.noFeedItems').removeClass('c40hide'); //display message container 
            C40CommunityStyles.registerFilterEvents(); //setup for next time
		}
		else if (C40CommunityStyles.filterPollingIndex++ > (C40CommunityStyles.maxseconds)) {//give up after 20 seconds
    	    if (C40CommunityStyles.debug) { console.log('C40CommunityStyles clear filter polling interval'); }
			window.clearInterval(C40CommunityStyles.filterPollingInterval); 
            C40CommunityStyles.registerFilterEvents(); //setup for next time
		}

    }
};

var C40CoveoOverride = {
	debug: false, //XXX set this to true to get more console logs
	alreadyinitialized: false, //this is set once the results events are registered
	initPollingInterval: -1,	//used as a unique identifier for setinterval and clearinterval 
	initPollingIndex: -1,		//used to force a runaway setinterval to stop
    maxseconds:20,
	init: function() {
		if (C40CoveoOverride.alreadyinitialized) { 
			if (C40CoveoOverride.debug) { console.log('C40CoveoOverride already initialized');}
			return;
		}
		console.log('C40CoveoOverride.init()'); 
		//XXX Coveo's doc on how to style/javascript their components doesn't work; 
		//static resources doesn't seem to work;
		//when document.ready and DOMContentLoaded events run, Coveo's object and components 
		//don't exist yet;
		//A polling approach, while ugly, is the only working solution at this point. 
		//If you can refactor this another way, go for it
		C40CoveoOverride.initPollingIndex=0;
		C40CoveoOverride.initPollingInterval = window.setInterval(C40CoveoOverride.initPolling, 1000);
	},
	initPolling: function() {
		if (C40CoveoOverride.debug) { console.log('C40CoveoOverride.initPolling(): '+C40CoveoOverride.initPollingIndex);}
		if (C40CoveoOverride.alreadyinitialized) { 
			if (C40CoveoOverride.debug) { console.log('C40CoveoOverride already initialized');}
			window.clearInterval(C40CoveoOverride.initPollingInterval);
			return;
		}
		if (typeof Coveo != "undefined") {
			window.clearInterval(C40CoveoOverride.initPollingInterval);
			C40CoveoOverride.registerCoveoEvents();
			
			C40CoveoOverride.initPollingInterval=window.setInterval(C40CoveoOverride.styleExistingResults,1000);//XXX we get a race so we'll check at the beginning of the function to see if everything we need is there
		}
		else if (C40CoveoOverride.initPollingIndex++ > C40CoveoOverride.maxseconds) {//give up after 20 seconds
			if (C40CoveoOverride.debug) { console.log('C40CoveoOverride could not initialize');}
			window.clearInterval(C40CoveoOverride.initPollingInterval);
		}
	},
	registerCoveoEvents: function() {	
		if (C40CoveoOverride.debug) { console.log('registerCoveoEvents(): '); }
		if (C40CoveoOverride.alreadyinitialized) { 
			if (C40CoveoOverride.debug) { console.log('C40CoveoOverride already initialized');}
			window.clearInterval(C40CoveoOverride.initPollingInterval);
			return;
		}
		if ($('#search').length > 0) { 	
			C40CoveoOverride.registerSearchResultEvents();
  			Coveo.init(document.querySelector("#search"));
		}
		else { //search results haven't been setup yet
			C40CoveoOverride.registerReinitEvents();
		}
	},
	registerSearchResultEvents: function() {
		if (C40CoveoOverride.debug) { console.log('C40CoveoOverride.registerSearchResultEvents() - registering newResultDisplayed event to style external results'); }
		
		C40CoveoOverride.alreadyinitialized = true; //let's just initialize the once?
		root = document.querySelector("#search");
		//Coveo.$$(root).on("newResultDisplayed", function(e,args) { //XXX does this work better?
		$('.cC40CustomThemeLayout').on('newResultDisplayed', function(e,args) {
			if (C40CoveoOverride.debug) { console.log('#search.newResultDisplayed(): '+args.result.title); }
			C40CoveoOverride.styleInitResult(args.result, args.item);
		});
	},
	registerReinitEvents: function() {
		if (C40CoveoOverride.debug) { console.log('registerReinitEvents(): '); }
		if (C40CoveoOverride.alreadyinitialized) { 
			if (C40CoveoOverride.debug) { console.log('C40CoveoOverride already initialized');}
			window.clearInterval(C40CoveoOverride.initPollingInterval);
			return;
		}
		$('.cC40CustomThemeLayout').on('querySuccess', function(e) {
			if (C40CoveoOverride.debug) { console.log('.cC40CustomThemeLayout.querySuccess()'); }
			if (C40CoveoOverride.alreadyinitialized) { //XXX this works if the coveo events are attached to .cC40CustomThemeLayout instead of #search
				if (C40CoveoOverride.debug) { console.log('C40CoveoOverride already initialized - Skipping');}
				window.clearInterval(C40CoveoOverride.initPollingInterval);
				return;
			}
			C40CoveoOverride.registerSearchResultEvents();
		});
	},
	styleInitResult: function(result, resultitem) {
		if (C40CoveoOverride.debug) { console.log('C40CoveoOverride.styleInitResult()');}
		C40CoveoOverride.styleExternalResult(resultitem, (result.raw.sfisoriginalcontentc == "false"));
		C40CoveoOverride.styleInternalResult(resultitem, (result.raw.sfisoriginalcontentc == "false"), result.raw.sffeaturedimagec);
	},
	styleExternalResult: function(resultitem, notorig) {	  
		var classname = 'c40resultisoriginal';
		if (notorig) {
			classname = 'c40resultnotoriginal';
		}
		$(resultitem).addClass(classname);
	},
	styleInternalResult: function(resultitem, notorig, imageurl) {
		if (notorig) {return;}
		var htmlchilpre = '<div class="c40result slds-grid" data-aura-rendered-by="5:92;a"><div class="c40resulttextcol slds-col slds-size_1-of-1 slds-medium-size_8-of-12 slds-large-size_2-of-3 slds-order_2 slds-medium-order_1 slds-large-order_1" data-aura-rendered-by="6:92;a"></div></div>';
		var htmlchilpost = '<div class="slds-col slds-size_1-of-1 slds-medium-size_4-of-12 slds-large-size_1-of-3 slds-order_1 slds-medium-order_2 slds-large-order_2" data-aura-rendered-by="52:92;a"><div class="article__image" style="background-image: url('+imageurl+');" data-aura-rendered-by="53:92;a"></div>';

		var coveoresultframe  = $($(resultitem).find('.coveo-result-frame').children()[0]).detach();
		$(resultitem).append(htmlchilpre);
		$(resultitem).find('.c40resulttextcol').append(coveoresultframe);
		$(resultitem).find('.c40result').append(htmlchilpost);
		
	},
	styleExistingResults: function() {
		if (C40CoveoOverride.debug) { console.log('C40CoveoOverride.styleExistingResults()');}
		var existingResults = $('.CoveoResult').length != ($('.CoveoResult.c40resultisoriginal').length + $('.CoveoResult.c40resultnotoriginal').length)
		if (C40CoveoOverride.debug) { console.log('.CoveoResult length: ' + $('.CoveoResult').length);}

		var dataloaded = $('.CoveoResult').find('[data-field="@sfisoriginalcontentc"] span').length > 0;
		if (!dataloaded) {
			if (C40CoveoOverride.debug) { console.log('Data not loaded: ' + C40CoveoOverride.initPollingIndex);}
			if (C40CoveoOverride.initPollingIndex++ > 20) {//give up after 20 seconds
				if (C40CoveoOverride.debug) { console.log('Data not loaded. Skipping.');} 
				window.clearInterval(C40CoveoOverride.initPollingInterval);
			}
		}	
		else if (existingResults && dataloaded) {
			$.each($('.CoveoResult'), function() {
				if (C40CoveoOverride.debug) { console.log('C40CoveoOverride.each .CoveoResult');}
				if (C40CoveoOverride.debug) { console.log($(this).find('[data-field="@sfisoriginalcontentc"]')); }
				var notorig = ($(this).find('[data-field="@sfisoriginalcontentc"] span').text() == "false");
				var imageurl = $(this).find('[data-field="@sffeaturedimagec"] span').text();
				C40CoveoOverride.styleExternalResult(this, notorig);
				C40CoveoOverride.styleInternalResult(this, notorig, imageurl);
			});	
			window.clearInterval(C40CoveoOverride.initPollingInterval); //only clear the interval if we've styled the results
		}
	}
};
