/**
 * @author ilazarte
 */

if (typeof NPR === 'undefined') 
{
    NPR = {};
} 

if (!NPR.reg)
{
    NPR.reg = {};
}

/**
 * A list of all the states and their lower cases.
 */
NPR.reg.STATES = ["alabama","al","alaska","ak","american samoa",
        "as","arizona","az","arkansas","ar","california","ca",
        "colorado","co","connecticut","ct","delaware","de",
        "district of columbia","dc","federated states of micronesia","fm",
        "florida","fl","georgia","ga","guam","gu","hawaii","hi","idaho",
        "id","illinois","il","indiana","in","iowa","ia","kansas","ks",
        "kentucky","ky","louisiana","la","maine","me","marshall islands","mh",
        "maryland","md","massachusetts","ma","michigan","mi","minnesota","mn",
        "mississippi","ms","missouri","mo","montana","mt","nebraska","ne",
        "nevada","nv","new hampshire","nh","new jersey","nj","new mexico","nm",
        "new york","ny","north carolina","nc","north dakota","nd","northern mariana islands",
        "mp","ohio","oh","oklahoma","ok","oregon","or","palau","pw","pennsylvania",
        "pa","puerto rico","pr","rhode island","ri","south carolina","sc","south dakota",
        "sd","tennessee","tn","texas","tx","utah","ut","vermont","vt","virgin islands",
        "vi","virginia","va","washington","wa","west virginia","wv","wisconsin","wi","wyoming","wy"];

/**
 * This is a static function to render a station autocomplete.
 * It doesn't have a default manner to trigger its own execute.
 * It exposes an execute method which external entities can bind to for that purpose.
 * 
 * The class will create a div called "stationsac" on the element once it's created
 * It will append all results to the div under a ul with the id "stationsul"
 * 
 * Css classes applied:
 * stationsacHighlight applied to text in the lis via a span if it matches a text input string.
 * stationsacSelected applied to the entire li when the user hovers.
 */
NPR.reg.stationfinder = function() {
    
    var STATES = NPR.reg.STATES;
    
    var DELAY = 500;
    
    var TIMEOUT = 3000;
    
    var TIMEOUT_ERR_MSG = 'System problem - please try again later.';
    
    var DEFAULT_ERR_MSG = 'No matching station was found.';
    
    var INITIAL_MSG = 'Type a zip code, city and state, or call letters.';
    
    var NO_OP = function() {};
    
    /** 
	 * These are organization status ids which we need to exlude the stations based on them. 
	 * Jira ticket: SFW-4655. You can get all of these from type_org_status table in cms database.
	 */    
    var EXCLUDE_STATUS_IDS = "2,3,11,13,14,19,21";

    /**
     * A reference to the ul node.
     */
    var stationsUl;
    
    var errMsg = '';
    
    /**
     * Render that little helper box under the input tag.
     * This is used to begin the initial process.
     */
    function suggest(error) {
        try {

            var input = $('#station_selector').get(0);
            if (typeof input == 'undefined' || input === null) {
                return;
            }

            var parent = $(input).parent('li');
            var offset = $(parent).offset();
            var height = $(parent).height();

            var position = {
                left : offset.left,
                top : offset.top + height
            };

            $('#stationsac').remove(); // try to avoid multiple items
            $('<div></div>')
                .attr('id', 'stationsac')
                .click(function() {
                    $('#stationsac').remove();                 
                })
                .html('<ul id="stationsul"></ul>')
                .css('display', 'none')
                .appendTo(document.body);

            if (error) {
                errMsg = error;
            }

            if (errMsg) {
                $('<li></li>').addClass('stationsfail').css('cursor', 'default').text(errMsg).appendTo('#stationsul');
            } else {
                $('<li></li>').addClass('stationsfail').css('cursor', 'default').html(INITIAL_MSG).appendTo('#stationsul');            
            }

            $('#stationsac')
                .css('left', position.left)
                .css('top', position.top)
                .css('position', 'absolute')
                .css('display', 'block');   
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, suggest', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }

    /**
     * Select the element visually 
     * @param {Object} el
     */
    function highlight(el) {
        try {
            $(el)
                .addClass('stationsacSelected')
                .siblings()
                .removeClass('stationsacSelected');
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, highlight', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }

    /**
     * Destroy the current dropdown.
     * This is invoked after every key since the ac is constantly redrawing itself.
     * @param {Object} message
     */    
    function destroy(message) {
        try {
            $('#stationsac').remove();
            errMsg = '';
            if (!message) {
                message = INITIAL_MSG;    
            }
            suggest(message);
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, destroy', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }
    
    /**
     * Kill function which doesn't render a new tooltip.
     */
    function kill() {
        try {
            $('#stationsac').remove();
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, kill', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }
    
    /**
     * Selects the currently selected item which is found via selected .stationsacSelected.
     */
    function select() {
        try {
            var el = $('.stationsacSelected').get(0);
            if (el === null || typeof el === 'undefined') {
                return;
            }

            var orgId = $(el).data('orgId');
            var nameId = $(el).data('nameId');
            
            /* Don't allow duplicate orgIds.
             * http://bugzilla.npr.org/show_bug.cgi?id=8191
             */
            var exists = false;
            $('input[name="public_user_stations[]"]').each(function() {
                if (this.value === orgId) { 
                   $(this).parent('.stationselected').fadeOut('fast').fadeIn('slow');
                   exists = true; 
                } 
            });

            if (exists) {
                destroy(); 
                return; 
            }

            var currLi = $("#stationinputs > li:last").get(0);
            var currInput = $(currLi).find("input").get(0);
            var width = currInput.offsetWidth;
            var height = currInput.offsetHeight;

            var clone = $(currLi).clone();

            $('<div></div>')
                .addClass('stationselected')
                .width(width)
                .html('<div class="stationstext">' + nameId +
                    '</div><input type="hidden" name="public_user_stations[]" value="' + orgId + '" />' + 
                    '<div class="btn_minus" style="font-family:Verdana; color:#FFFFFF; vertical-align:middle;">&nbsp;<b>x</b>&nbsp;</div>')
                .prependTo(currLi);

            var btnWidth = $(currLi).find('.btn_minus').width();
            $(currLi).find('.stationselected').width(width + btnWidth);
            $(currLi).find('.stationstext')
                .width(width)
                .height(height);

            $(currLi).find('input[type="text"]').remove();

            $(currLi).find('.btn_minus')
                .css('cursor', 'default')
                .click(function() {
                    $(currLi).remove();
                    destroy();
                });

            $(clone).insertAfter(currLi);
            $(clone).find('input')
                .delay({
                    delay: DELAY,
                    event: 'keypress',
                    fn: NPR.reg.stationfinder.multiexecute
                })
                .attr('value', '')
                .focus(function() { destroy(); })
                .blur(function () { }) // see note below
                .focus();

            destroy();

            // if this is the overlay registration, resize the frame to handle the longer list
            if (window.parent != undefined  && window.parent !== window)
            {
                NPR.resizeParentIframe(window.parent.NPR.community.overlayIframeId, '.overlay', 90);
            }
        
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, select', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }

    /**
     * Handle the control keys: up down enter esc.
     * @see http://www.ryancooper.com/resources/keycode.asp
     */
    function handleKey(event) {
        try {
            var update = function(el) {
                if (el === null && el === 'undefined') {
                    $(stationsUl).find('li:first').addClass('stationsacSelected');
                } else {
                    highlight(el);
                }
            };

            switch (event.keyCode) {
                case 13: // enter
                    select();
                    event.preventDefault();
                break;                
                case 27: // escape
                    kill();
                    event.preventDefault();
                break;
                case 38: // up
                    update($('.stationsacSelected').prev());
                break;
                case 40: // down
                    update($('.stationsacSelected').next());
                break;
            }
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, handleKey', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }
    
    /**
     * Gather the info to be passed into the ajax invocation.
     * @param {Object} value
     */
    function toRequestData(value) {
        try {
        	
            var data = {
                format: 'json',
                excludeStatusIds: EXCLUDE_STATUS_IDS,
                searchTerm: value
            };

            return data; 
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, toRequestData', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }   

    /**
     * Generate the autocomplete.
     * 
     * @param {Object} cfg Container object to be rendered.
     *     Has the following properties:
     *     - requestData, The data used in the request.
     *     - json, The response data
     *     - inputEl, The input element which triggered the execution.
     *     - position, The position.left and position.top for the new div.
     */
    function render(cfg) {
        try {
            var data = cfg.json;
            if (typeof data === 'undefined' || !data || !data.station || !data.station[0]['id']) {
                destroy(DEFAULT_ERR_MSG);
                return;
            }
            $('#stationsac').remove();

            var requestData = cfg.requestData;
            var inputEl = cfg.inputEl;
            var position = cfg.position;
            var isMulti = cfg.isMulti;

            $('<div></div>')
                .attr('id', 'stationsac')
                .css('display', 'none')
                .html('<ul id="stationsul"></ul>')
                .appendTo(document.body);

            $('#stationsac')
                .css('left', position.left)
                .css('top', position.top)
                .css('position', 'absolute');                                 

            var ulEl = $('#stationsul').get(0);
            stationsUl = ulEl;

            var iterable = data.station;
            
            $.each(iterable, function(i, station) {
            	
                var orgId = station['id'];
                var band = station.band.$text;
                var cltr = station.callLetters.$text;
                var freq = station.frequency.$text;
                var status = station.memberStatus.$text;

                // don't include translators
                if (status === "Translator") {
                	return;
                }

                var tagline = null;
                if (station.tagline[0].$text) {
                    tagline = station.tagline[0].$text;
                } else  {
                    tagline = '&nbsp;';
                }

                var text = '<div style="width:100px;float:left;">' + cltr + '</div> ' + 
                     freq + ' ' + band + '<br />' + tagline;

                var nameId = freq + ': ' + cltr + '-' + band;

                var regex = null;
                if (requestData.searchTerm) {
                    regex = new RegExp(requestData.searchTerm, "ig");
                    text = text.replace(regex, "<span class='stationsacHighlight'>" + requestData.searchTerm + "</span>");    
                }                               

                var hoverHighlight = function() {
                    highlight(this);
                };

                $('<li></li>')
                    .css('cursor', 'default')
                    .html(text)
                    .data('orgId', orgId)
                    .data('nameId', nameId)
                    .hover(hoverHighlight, NO_OP)
                    .click(function() {
                        if (isMulti) {
                            select();
                        } else{
                            destroy(); // not really handling non-multi situation yet.                                
                        }
                    })
                    .appendTo(ulEl);
            });

            highlight($(ulEl).find('li:first'));

            $('#stationsac').css('display', 'block');

            // if this is the overlay registration, resize the frame to handle the longer list
            if (window.parent != undefined  && window.parent !== window)
            {
                NPR.resizeParentIframe(window.parent.NPR.community.overlayIframeId, '.overlay', $('#stationsac')[0].scrollHeight);
            }
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, render', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }

    /**
     * Respond to the event which will start the autocomplete process.
     * The hardcoded parentage here is an "li" dependency.  Ideally
     * It could choose the nearest block tag.
     */
    function execute(isMulti, inputEl) {
        try {
            $(document.body).unbind('keyup', handleKey);
            $(document.body).keyup(handleKey);
            var parent = $(inputEl).parent('li');
            var offset = $(parent).offset();
            var height = $(parent).height();

            var position = {
                left : offset.left,
                top : offset.top + height
            };

            var requestData = toRequestData(inputEl.value);
            if (requestData === null) {
                if (inputEl.value.length < 3) {
                    destroy();
                } else {
                    destroy(DEFAULT_ERR_MSG);
                }

                if (window.parent != undefined && window.parent !== window)
                {
                    NPR.resizeParentIframe(window.parent.NPR.community.overlayIframeId, '.overlay', 90);
                }            
                return;
            }

            var errorTimeout = setTimeout(function() { destroy(DEFAULT_ERR_MSG); }, TIMEOUT);

       		$.getJSON('/templates/reg/jsonStationSelector.php', requestData,            
                function(data) {
                    clearTimeout(errorTimeout);
                    render({
                        requestData : requestData,
                        json: data,
                        inputEl: inputEl,
                        position: position,
                        isMulti: isMulti
                    }); 
                });
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.stationfinder, execute', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }
    
    return {
        /**
         * Expose only the execute method.
         */
        execute : function() {
            execute(false, this);
        },
        multiexecute : function() {
            execute(true, this);
        },
        kill : function() {
            kill();            
        },
        destroy : function() {
            destroy();            
        },
        handleKey : handleKey,
        DELAY : DELAY
    };
}();

/**
 * Nifty logger.  Gotta love JS.
 * Dumps the output to a ul named "log".
 * Style the lis based on debug, info, error, warn.
 */
NPR.reg.log = function() {
    
    function _log(level, msg) {
        try {
        
            var date = new Date();
            var els = $("#log > li").get();
            if (els !== null && els.length > 25) {
                 $(els[0]).remove();   
            }

            $('<li></li>')
                .addClass(level)
                .html(date.toUTCString() + " [" + level.toUpperCase() + "] : " + msg)
                .appendTo('#log');
        }
        catch (e) {
            NPR.messaging.exception(e, 'reg.js', 'NPR.reg.log, _log', NPR.messaging.constants.REG_JS_ERROR);
        }           
    }
    
    return {
        debug : function(msg) { _log('debug', msg); },
        warn : function(msg) { _log('warn', msg); },
        error : function(msg) { _log('error', msg); },
        info : function(msg) { _log('info', msg); }
    };
}();

/**
 * Execute initializations on pages we know have station selectors.
 */
AddNamespace("NPR.onready.reg");
NPR.onready.reg.reg = function() {
    try {
        $('.nl_view_sample_link').click(function() {
            window.open(this.href, "sampleNewsletter", "width=580,height=716,scrollbars=yes,status=no");
            return false;        
        });

        $('.stationfinder').delay({
            delay: NPR.reg.stationfinder.DELAY,
            event: 'keypress',
            fn: NPR.reg.stationfinder.multiexecute
        });

        /*
         * fix for IE7 google toolbar issues.
         */
        $('form').find('input[type=text]').focus(function() {
             if (this.value.indexOf('google') > -1) {
                 this.value = '';
             }   
        });

        var currInput = $('#station_selector').get(0);
        if (typeof currInput == 'undefined' || currInput === null)
        {
            return;
        }

        $(document.body).keyup(NPR.reg.stationfinder.handleKey);

        currInput.setAttribute("autocomplete", "off");

        var width = currInput.offsetWidth;
        var height = currInput.offsetHeight;

        var divbutton = $('.stationselected').find('.btn_minus').get(0);
        var btnwidth = $(divbutton).width();

        $('.stationselected').width(width + btnwidth);

        $('.stationselected')
            .find('.stationstext')
            .width(width)
            .height(height);

        $('.stationselected')
            .find('.btn_minus')
            .click(function() {
               $(this).parents('li').remove();
               NPR.reg.stationfinder.destroy();
            });

        $('#station_selector').focus(function() {
            NPR.reg.stationfinder.destroy();
        });

        /*
         * The blur handler is removed again.
         * cannot figure out a way to queue events which 
         * will not kill the stationfinder before a selection has taken place.
         * instead, you can click on the tooltip or press Esc to clear it now.
         * Leaving it in here as a warning.
         */
        $('#station_selector').blur(function() {
        });


        // Bug 7998: Remove user prompt from station selector when user clicks on another input or select element 
        $('input').focus(function(e) {
            if ((e.target && e.target.id != 'station_selector') || (e.srcElement && e.srcElement.id != 'station_selector'))
            {
                 $('#stationsac').remove();
                 $('#station_selector').val('');
            }
        });

        $('select').focus(function(e) {
            if ((e.target && e.target.id != 'station_selector') || (e.srcElement && e.srcElement.id != 'station_selector'))
            {
                 $('#stationsac').remove();
                 $('#station_selector').val('');
            }
        });    

        $(window).resize(function() {
            // if this is the overlay registration, we may have resized the iframe
            // to handle the longer stations list
            // so, don't kill the stationfinder
            if (window.parent === window)
            {
                NPR.reg.stationfinder.kill();
            }
        });
    }
    catch (e) {
        NPR.messaging.exception(e, 'reg.js', ' document.ready', NPR.messaging.constants.REG_JS_ERROR);
    }           
};

