//Setup a PlanetTagger namespace
var PT = PT || {};

PT.fsm = function( e, options ){
	
	//show the user that this target is loading
	SDNA.loading(options.target);
	
	if( options.url.match(/.htm/) ){
		
		Window.pop( 
			options.url,
			{
			   width:600,
				close: function(){
					SDNA.loaded(options.target);
				}
			} 
		);
	}	
};

PT.fsm.unpromote = function( e, options ){
	if( options.target ){
		SDNA.loading(options.target);
	}
	
	$j.getJSON( 
		options.url, 
		function(response){
			
			//attach the target to the response
			$j.extend(response,options);		
			
			if(response.success == true){
			   
				PT.fsm.unpromoted( response );
				
				SDNA.loaded(response.target);
				
			//There was an error unpromoting	
			}else{
					
				Window.pop( response.message, {error:true} );
				
			}
		}
	);
};

PT.fsm.unpromoted  = function( response ){
	
	// if there a no more promo message
	// for this entity then 
	if ( response.promo_count < 1 ) {
	  PT.fsm.unpromoted.syncDOM( response );
	}
	SDNA.Event.publish('unpromote',response);

};

/**
 * 
 */
PT.fsm.unpromoted.syncDOM = function(response){

	//Find the FSM menu and replace with the "Promote" button
	$j("span.promote")
		.filter('.' + response.entity + '_' + response.id)
		.each(
			function(){
				SDNA.loaded( this );
				
				$this = $j(this);
				$action = $j(response.html);				
				var sClass = $this.attr('class').replace(/promote|unpromote/,'');
				$action.addClass( sClass ).find('.button').addClass( sClass );
				$this.replaceWith( $action );

			}
		);

};


PT.fsm.promoted  = function( response ){
	
	PT.fsm.promoted.syncDOM( response );
	
	SDNA.Event.publish('promote',response);

};

PT.fsm.promoted.syncDOM = function( response ){

	//Find all follow links on the page that are the
	//right entity (location, event, user)
	//and the right id
	$j("." + response.action)
		.filter('.' + response.entity + '_' + response.id)
		.filter('a,span')
		.each(
			function(){
				
				SDNA.loaded( this );
				
				$this = $j(this);
				
				$action = $j(response.menu);
				var sClass = $this.attr('class').replace(/promote/,'');
				$action.addClass( sClass ).find('.button').addClass( sClass );
				
				if( !$this.hasClass('button') ){
					$action.removeClass('button');
				}				
				$this.replaceWith( $action );

			}
		);
};



PT.fsm.promoteOptions = {};

PT.fsm.promoteOptions.createMenu = function( trigger ){

	//ref the jquery trigger
	var $trigger = $j(trigger);
	
	//create the menu
	var menu = new Menu( trigger );
		
	//get the data associated with this menu	
	var data = eval('(' + $trigger.attr('data') + ')');
	
	var sNiceName = data.entity == 'location'? 'place' : sNiceName;
	sNiceName = data.entity == 'event'? 'event' : sNiceName;
	sNiceName = data.entity == 'user'? 'person' : sNiceName;
	
	var sClassId = data.entity.toLowerCase() + '_' + data.id;
	
	menu.addOptions(
		{
			action: 		'/ajax/Admin/FSMList.htm/entity_id:' + data.id + '/entity_type:' + data.entity,
			className: 	'promote manage ' + sClassId,
			label:		'Manage Promotions'
		},
		{	
			action: 		'/ajax/Admin/FSMForm.htm/entity_id:' + data.id + '/entity_type:' + data.entity,
			className:  'promote ' + sClassId,
			label:		'Add a promotion for this ' + sNiceName
		}
	);
	
	//last, return the menu
	return menu;

};

PT.fsm.promoteOptions.click = function( e ){	              
	
	//keep this link from functioning
	if(e){
		e.preventDefault();
		e.stopPropagation();
	}
	
	//get a ref to this link
	var $this = $j(this);	
	
	//get the menu
	var mPromote = Menu.getMenuFor( this );
	
	if( !mPromote ){
		mPromote = PT.fsm.promoteOptions.createMenu( this );
	} 
	
	//toggle open/closes the menu
	mPromote.toggle();
	
	return false;	

};

PT.fsm.click = function( e ){	              
	e.preventDefault();
	SDNA.Event.trigger(
		'pop_fsm',  
		{ 
			url: $j(this).attr('href'), 
			target: this 
		}
	);
};


PT.fsm.unpromote.click = function( e ){	              
	e.preventDefault();
	
	if (!confirm('Are you sure?')) return false;
	
	SDNA.Event.trigger(
		'unpromote',  
		{ 
			url: $j(this).attr('href'), 
			target: this 
		}
	);
};

/**
 * Handle Admin options
 */
PT.fsm.admin = { edit : {}, remove : {} };

/**
 * Edit the FSM form from admin page
 */
PT.fsm.admin.edit.click = function (e) {
    e.preventDefault();
    
    // see callback below where this is referenced
    PT.fsm.admin.edit.oldRow = $j(this).parents('tr'); 
    
    SDNA.Event.trigger(
        'pop_fsm',  
        { 
            url: $j(this).attr('href'), 
            target: this 
        }
    );
};

/**
 * The old row before edits
 */
PT.fsm.admin.edit.oldRow = null;

/**
 * Handle what to do on the admin page
 * when the FSM form is submitted
 * - Instead of reloading the page (slow)
 *   we replace the row returned from the server
 * - This handles the alternating row color
 *   and also a little color effect to highlight
 *   the edited row 
 */
PT.fsm.admin.edit.callback = function (event, response) {
    if (!PT.fsm.admin.edit.oldRow) {
        return;
    }
    var fsmNewRow = $j(response.row);
    // give the new row a "new edit" highlight
    fsmNewRow.find('td').addClass('new_edit');
    // grab the old css class
    var oldCssClass = PT.fsm.admin.edit.oldRow.attr('class');
    // replace old row with new row
    PT.fsm.admin.edit.oldRow.replaceWith(fsmNewRow);
    // after 1.5 seconds replace the new edit class with the original class
    setTimeout(
        function () { 
            fsmNewRow.find('td').removeClass('new_edit');
            fsmNewRow.attr('class', oldCssClass); 
        }, 1500
    );
};

/**
 * Delete an FSM
 */
PT.fsm.admin.remove.click = function(e){
	e.preventDefault();
	
	SDNA.loading(this);
	$this = $j(this);
	
	var views = parseInt($this.attr('data-views'));
	var uniqueViews = parseInt($this.attr('data-unique-views'));
	
	if (confirm('Are you sure? Views: ' + views + ', Uniques: ' + uniqueViews)) {
	    
	    
	    var deletedRow = $j(this).parents('tr');
	    $j.post(
	        $this.attr('href'),
	        $this.attr('json'),
	        function(response){
	            // give a deleted row highlight color
	            deletedRow.attr('class', 'deleted_row');
	            var handleDeletedRow = function () {
	                // remove the deleted row
	                deletedRow.remove();
	                // traverse the trs and set the
	                // alternate colors correctly again
	                $j('#admin_fsm_list tbody tr').each(function (index) {
	                    var row = $j(this);
	                    if (index % 2) {
	                        row.attr('class', '');
	                    } else {
	                        row.attr('class', 'alternate_color');
	                    }
	                });
	            };
	            // delete the row after a short pause
	            setTimeout(handleDeletedRow, 1000);
	        },
	        'json'
	    );
	} else {
	    SDNA.loaded(this);
	}
};

/**
 * Show new promo message, replaces previous html
 * - if there are no promo messages the link is removed
 * 
 * @param Object e
 * @param Object options SDNA.Event options
 */
PT.fsm.showPromo = function (e, options) {
    
    SDNA.loading(options.target);
    
    var $this = $j(options.target);
    
    $j.getJSON(
        options.href, 
        {}, 
        function (response) {
            SDNA.loaded(options.target);
            var featuredMessage = $this.parents('.featured_message').eq(0);
            if (response.fsm_count > 0) {
                featuredMessage.replaceWith(response.html);
            } else {
                featuredMessage.html('<div style="text-align: center; font-style: italic;">No more messages to display.</div>');
                setTimeout(function () { featuredMessage.remove(); }, 2000);
            }
        }
    );
};

/**
 * Show new promo message click handler
 * 
 * @param Object e
 */
PT.fsm.showPromo.click = function (e) {
    e.preventDefault();
    if (PT.fsm.autoRefresh) {
        PT.fsm.autoRefresh.restartTimer();
    }
    SDNA.Event.trigger(
        'refresh_promo_message',
        {
            target : this,
            href : $j(this).attr('data-href')
        }
    );
};

/**
 * @var AutoRefresh instance (see .bind below where this is setup)
 */
PT.fsm.autoRefresh = null;

/**
 * Search field handles loading search results
 * as-you-type.
 * 
 * @author davidbjames
 */
PT.fsm.searchField = function () {
    
    // Setup timer for managing keyup events
    // Essentially, we find the right balance
    // between search responsiveness and server load
    // as well as handle fringe cases in user behavior
    var timer = new SDNA.utils.Timer(1000);
    timer.start();
    
    // Initially we show all results, and
    // also show all results if the user
    // deletes the search field
    var allResults = true;
    
    // Remove the loading animation whenever
    // a timer or process is complete
    var loaded = function () {
        SDNA.loaded($j('#fsm_search span.search_count'));
        timer.stop();
    };
    
    // Setup ajax search to handle
    // injecting the search results
    // and displaying number of results
    var searchOptions = {
        url : '/Admin/FSM',
        type : 'POST',
        dataType : 'json',
        success : function (response) {
            $j('div.admin_fsm_list').html(response.html);
            var countDisplay = '';
            switch (response.count) {
                case 0 :
                    countDisplay += 'No results';
                    break;
                case 1 :
                    countDisplay += '1 result';
                    break;
                default :
                    countDisplay += response.count + ' results';
            }
            loaded();
            $j('#fsm_search span.search_count').html(countDisplay);
        }
    };
    
    // Callback to submit the search 
    var submitSearch = function () {
        // stop the timer
        timer.stop();
        // if the search string is at least four characters
        // after whitespace is removed left and right, then submit
        var searchString = $j('#fsm_search input').val();
        if (searchString.replace(/^\s+|\s+$/g, "").length > 3) {
            searchOptions.data = { search_string : searchString };
            // submit to server via ajax
            $j.ajax(searchOptions);
            allResults = false; // set allResults false because now we display search results
            return false;
        } else {
            loaded();
        }
    };
    
    // Check that we are reacting to a sensible
    // keycode... this needs development/testing
    // @todo develop/test
    var isValidKey = function (keyCode) {
        return ((keyCode >= 41 && keyCode <= 127) || keyCode === 8);
    };
    
    // Handle all keyup events in the search field
    $j('#fsm_search input').keyup(function (event) {
        
        SDNA.loading($j('#fsm_search span.search_count'));
        
        // if there is something in the search field
        if ($j(this).val().length) {
            // if the timer is not running any more
            if (!timer.running) {
                if (isValidKey(event.keyCode)) {
                		// for valid characters, start timer
                		// and submit search when complete
                    timer.start(submitSearch);
                } else {
                		// for invalid characters, simply
                		// start a timer and turn off loading
                		// animatiion when done
                    timer.start(loaded);
                }
            }
        } else { // handle empty search field (they deleted it)
            if (!allResults) { // only reload once (so they can't hit del, del, del...)
                $j('div.admin_fsm_list').load('/Admin/FSM/reload:true', {}, function () { allResults = true; loaded(); });
            }
            // remove display of search count, the non-breaking spaces
            // are necessary for loading animation to work
            $j('#fsm_search span.search_count').html('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
            // start a new timer
            timer.start(loaded);
        }
    });
    
};


PT.fsm.displayMetrics = function (e, options) {
    
    Window.pop( 
        options.url,
        {
           width:600,
           close: function(){
                SDNA.loaded(options.target);
            }
        } 
    );
};

PT.fsm.displayMetrics.click = function (e) {
    e.preventDefault();
    SDNA.Event.trigger(
        'pop_fsm_metrics',  
        { 
            url: $j(this).attr('href'), 
            target: this
        }
    );
};

PT.fsm.displayUserMetrics = {};

PT.fsm.displayUserMetrics.click = function (e) {
    e.preventDefault();
    $this = $j(this);
    if ($this.text() === "More Info") {
        $this.text("Less Info");
        $j(this).find('+ table').show();
    } else {
        $this.text("More Info");
        $j(this).find('+ table').hide();
    }
};

/**
 * Set up all live bindings for this namespace
 * @see pt.init.js
 */
PT.fsm.bind = function(){
    // Promo button/menu bindings
    $j('a.promote_options').live('click.promote_menu', PT.fsm.promoteOptions.click );
    $j('a.promote,a.promote.manage').live('click.promote', PT.fsm.click );
    $j('a.unpromote').live('click.unpromote', PT.fsm.unpromote.click );
    
    // FSM admin page bindings
    $j('#admin_fsm_list a.edit_fsm').live('click.edit_fsm', PT.fsm.admin.edit.click );
    $j('#admin_fsm_list a.delete_fsm').live('click.delete_fsm', PT.fsm.admin.remove.click );
    
    // Message bindings
    $j('a.refresh_promo_message').live('click.refresh_promo_message', PT.fsm.showPromo.click);
    
    // Initialize the search field
    PT.fsm.searchField();
    
    $j('a.display_fsm_metrics').live('click.display_fsm_metrics', PT.fsm.displayMetrics.click);
    $j('a.display_fsm_user_metrics').live('click.display_fsm_user_metrics', PT.fsm.displayUserMetrics.click);
    
    // setup auto refresh FSMs
    
    /**
     * Constructor function for auto refreshing FSMs
     * - triggers the click handler (above) which itself
     *   restarts the timer each time... which means
     *   the timer is restarted for auto AND manual refreshing
     */
    var AutoRefresh = function () {
        /**
         * Handle to the instance
         * (standard variable used in constructor functions)
         */
        var _instance = this;
        /**
         * Trigger the FSM to reload
         */
        var _refresh = function () {
            $j('a.refresh_promo_message').trigger('click');
        };
        /**
         * Restart the timer 
         */
        this.restartTimer = function () {
            _instance.timer.start(_refresh);
        };
        // by default, start the timer on page load
        this.restartTimer();
    };
    // setup timer 
    AutoRefresh.prototype.timer = new SDNA.utils.Timer(5000);
    // treat this as a constructor function, instantiate and let it run
    PT.fsm.autoRefresh = new AutoRefresh();
    
};

SDNA.Event.create('pop_fsm', PT.fsm);
SDNA.Event.create('unpromote', PT.fsm.unpromote);
SDNA.Event.create('refresh_promo_message', PT.fsm.showPromo);
SDNA.Event.create('pop_fsm_metrics', PT.fsm.displayMetrics);

SDNA.Event.subscribe('fsm_form_submit', PT.fsm.admin.edit.callback);