/*Object for attaching dynamic search functionality to an input text box*/

function LocationInputController( config )
{
    this.form = $('#' + config.form );
    this.keyword = config.keyword;
    this.return_func = config.return_func;
    this.url = "/ajax/area.php";
    this.display_structs = {};
    this.search_data = [];
    this.search_results = [];
    this.current_pointer = 0;
    this.dirty = true;
    this.geocoder = new google.maps.Geocoder();

    this.isDirty = function(){ return this.dirty; }
    this.makeDirty = function(){ this.dirty = true; }
    this.makeClean = function(){ this.dirty = false; }

    this.clearMenu = function(){ this.display_structs.menu.empty(); }
    this.hideMenu = function(){ this.display_structs.menu.css( 'display', 'none' ); }
    this.showMenu = function()
    {
        this.clearMenu();
        if( this.search_results.length < 1 )
        {
            this.hideMenu();
            return;
        }

        var lic = this;
        for( var i = 0; i < this.search_results.length; i++ )
        {
            var list_item = this.getRowContent( this.search_results[i] );
            list_item.attr( 'id', 'list_item_' + ( i+1 ) );
            this.display_structs.menu.append( list_item );

            list_item.mousedown( function( e ){ lic.setInputValue(); } );
            list_item.mouseover( this.onMouseOver( lic, i+1 ) );
        }
        this.display_structs.menu.css( 'display', 'block' );
    }

    this.onMouseOver = function( lic, index ){ return function( e ){ lic.setCurrentPointer( index ); }; }

    this.setMenuHighlight = function( highlight )
    {
        if( this.current_pointer == 0 ) return;
        var item = $( '#list_item_' + this.current_pointer );
        if( !highlight ){ item.removeClass( 'list_item_selected' ); }else{ item.addClass( 'list_item_selected' ); }
    }

    this.getRowContent = function( obj )
    {
        var cont_div = jQuery( document.createElement( 'div' ) );
        cont_div.css( 'float', 'left' );
        cont_div.css( 'clear', 'both' );
        cont_div.css( 'width', '100%' );

        var name_div = jQuery( document.createElement( 'div' ) );
        name_div.css( 'float', 'left' );
        name_div.css( 'margin', '5px 5px' );
        name_div.html( this.boldSubChars( obj.name, this.input.val() ) );

        var state_div = jQuery( document.createElement( 'div' ) );
        state_div.css( 'float', 'right' );
        state_div.css( 'margin', '5px 5px' );
        state_div.html( obj.state );

        cont_div.append( name_div );
        cont_div.append( state_div );
        return cont_div;
    }

    this.boldSubChars = function( original, to_bold ){ return original.replace( new RegExp( "(" + to_bold + ")", "gi" ), "<b>$1</b>" ); }

    this.setCurrentPointer = function( pointer )
    {
        this.setMenuHighlight();
        this.current_pointer = pointer;
        this.setMenuHighlight( true );
    }

    this.incrementPointer = function( key_code )
    {
        this.setMenuHighlight();

        if( key_code == "38" ) //moving up
        {
            if( this.current_pointer == 0 )
            {
                this.current_pointer = this.search_results.length;
            }
            else
            {
                this.current_pointer = Math.max( 1, this.current_pointer - 1 );
            }
        }
        else if( key_code == "40" ) //moving down
        {
            this.current_pointer = Math.min( this.search_results.length, this.current_pointer + 1 );
        }

        this.setMenuHighlight( true );
    }

    this.setInputValue = function()
    {
        if( this.current_pointer != 0 )
        {
            this.input.val( this.search_results[this.current_pointer-1].name );
            this.current_pointer = 0;
            this.hideMenu();
        }
    }

    this.attachPoint = function( point )
    {
        for( attr in point )
        {
            //have to prefix, bugs out when attribute passed is 'name'
            var attribute = this.form.find( 'input[name=area_' + attr + ']' );
            if( attribute.length )
            {
                attribute.val( ( point[attr] ) ? point[attr] : "" );
            }
            else
            {
                var attribute = jQuery( document.createElement( 'input' ) );
                attribute.attr( 'type', 'hidden' );
                attribute.attr( 'name', 'area_' + attr );
                attribute.val( ( point[attr] ) ? point[attr] : "" );
                this.form.append( attribute );
            }
        }
    }


    this.doReturn = function( point )
    {
        this.attachPoint( point );
        if( this.return_func && typeof this.return_func == "function" )
        {
            this.return_func( point );
        }
        else
        {
            this.form.unbind();
            this.form.submit();
        }
        this.makeDirty();
    }

    this.getGeocode = function()
    {
        var loc = this.input.val();

        var name = loc.split( "," );
        var area_obj = null;
        for( i = 0; i < this.search_data.length; i++ )
        {
            if( this.search_data[i].name.match( new RegExp( name[0], "gi" ) ) )
            {
                area_obj = this.search_data[i];
                break;
            }
        }

        if( !area_obj )
        {
            var lic = this;
            this.geocoder.geocode(
                { address: loc }, 
                function( results, status ){
                    if( status == google.maps.GeocoderStatus.OK )
                    {
                        var point_obj = ( results[0].geometry.location ) ? 
                            { latitude: results[0].geometry.location.lat(), longitude: results[0].geometry.location.lng() } : 
                            {};
                        lic.doReturn( point_obj );
                    }
                    lic.makeClean();
                }
            );
        }
        else
        {
            this.doReturn( { 
                name: area_obj.name,
                state: area_obj.state,
                latitude: area_obj.latitude, 
                longitude: area_obj.longitude 
            } );
        }
    }

    this.setSearchData = function( data )
    {
        this.search_data = data;
        if( this.input.val() != "" ) this.getGeocode();
    }

    this.requestAreas = function()
    {
        if( this.search_data.length < 1 )
        {
            var lic = this;
            $.ajax( {
                url: this.url,
                context: this,
                data: encodeURIComponent( 'keyword' ) + '=' + encodeURIComponent( this.keyword ),
                dataType: 'json',
                type: 'POST',
                success: function( data ){ lic.setSearchData( data ); }
            } );

            return;
        }

        this.search();
    }

    this.search = function()
    {
        if( this.input.val() == "" ){ this.hideMenu();return; }

        this.current_pointer = 0;
        this.search_results = [];

        for( i = 0; i < this.search_data.length; i++ )
        {
            if( this.search_data[i].name.match( new RegExp( "(^|\\s)" + this.input.val(), "ig" ) ) != null )
            {
                if( this.search_results.length < 10 ) this.search_results.push( this.search_data[i] );
            }
        }
        this.showMenu();
    }

    this.initialize = function()
    {
        this.input = this.form.find( 'input#location' );
        if( this.input.length != 1 ) return;

        this.display_structs.container = this.input.parent();

        //create menu
        var input_pos = this.input.position();
        var menu = jQuery( document.createElement( 'div' ) );
        menu.addClass( 'suggestion_menu' );
        menu.css( 'top', input_pos.top + this.input.outerHeight() + 'px' );
        menu.css( 'left', ( input_pos.left - 1 ) + 'px' );
        menu.css( 'width', ( this.input.outerWidth() < 355 ) ? 355 + 'px' : this.input.outerWidth() + 'px' );
        menu.css( 'z-index', '100' );
        this.display_structs.menu = menu;
        this.display_structs.container.append( menu );

        //register events
        var lic = this;
        this.input.blur( function( e ){ lic.hideMenu(); } );
        this.input.keyup( function( e ){
            if( e.keyCode == "40" || e.keyCode == "38" || e.keyCode == "39" || e.keyCode == "37" || e.keyCode == "13" ) return;
            lic.search();
        });
        this.input.keydown( function( e ) {
            if( e.keyCode == "40" || e.keyCode == "38" ){ lic.incrementPointer( e.keyCode ); } //Down or Up arrow keys
            else if( e.keyCode == "13" || e.keyCode == "9" ){ lic.setInputValue(); } //Enter or tab keys
        });
        this.form.submit( function( e ) { spottago.event.kill( e );lic.getGeocode(); });

        this.requestAreas();
    }
    this.initialize();
}

