﻿/// FILTER CLASS ///
//© 2008 SeatQuest LLC.

/// <reference path="framework.js" />
/// <reference path="zoomer.js" />
/// <reference path="debug.js" />
/// <reference path="xsl.js" />
function FILTER(args)
{
    this.actual_sections_ready=false;
    var _this=this;
    if(args){this.args=args;}
    
    //ELI will provide debug information.
    this.debug=this.args.debug;
    if(!this.debug){this.debug=new DEBUG();}
    this.zoomer=this.args.zoomer;
    this.price_ranges=this.args.price_ranges;
    
    //ELI will help manipulate XSL.
    this.xslt = new XSLT({debug:this.debug});
    
    //ELI set default args
    this.set_default_args();

    //ELI start looking for the ticket list DIV element.
    this.flags.load=true;
    framework.observe(this.args.id,'onload',function(){_this.load();});
    
    //ELI if we have XML and XSL urls we can start he download.
    if(this.args.xsl_url)
    {
        this.download();
        this.apply();
    }
    //initialize section selections
    this.reset_selected_sections();

};

//ELI default parameters
FILTER.prototype.args={
    id:null,
    xml_url:null,
    xsl_url:null,
    pre_render:null,
    post_render:null,
    pre_filter:null,
    post_filter:null,
    get_values:null,
    set_values:null,
    quantity_filter:null,
    sort_options:null,
    filter_options:null,
    delay_default:null, 
    debug:null,
    zoomer:null,
    sq_contains_coordinates:null,
    convert_from_tb:null,
    show_all:null,
    parking_tab:null,
    no_filtering_for_parking:null,
    wait_for_zoomer:null
}

FILTER.prototype.debug=null;
FILTER.prototype.xslt=null;
FILTER.prototype.xml=null;
FILTER.prototype.xsl=null;
FILTER.prototype.xsl_base=null;
FILTER.prototype.xsl_base_url=null;
FILTER.prototype.complete_xsl=null;
FILTER.prototype.xsl_for_conversion_url=null;



FILTER.prototype.flags={
    load:null,          //ELI FLAG which indicates that we are waiting for the ticket list DIV to load.
    download:null,      //ELI FLAG which indicates that we started a download.
    xml_ready:null      //ELI FLAG when xml_ready starts
};

FILTER.prototype.queue={
    apply:null,      //ELI apply() request was made but XSL & XML havent arrived yet.
    reset:null      //ELI reset() it is possible that a reset operation is requested before we downloaded the XML.
};

FILTER.prototype.load=function()
{
    this.flags.load=null;
    if(this.queue.apply){this.queue.apply();}
}

FILTER.prototype.set_default_args=function()
{
    //ELI quantity filter.
    if(!this.args.quantity_filter)
    {
        //ELI load default quantity filter.
        this.args.quantity_filter=[];
        this.args.quantity_filter[1]=[1,3,5,7,9,11,13];
        this.args.quantity_filter[2]=[2,4,5];
        this.args.quantity_filter[3]=[3,5,7,9,11,13];
        this.args.quantity_filter[4]=[4,6];
        this.args.quantity_filter[5]=[5,7,9,11];
        this.args.quantity_filter[6]=[6,8];
        this.args.quantity_filter[7]=[7,9];
        this.args.quantity_filter[8]=[8];    
    };
    
    if(!this.args.sort_options)
    {
        //ELI load default sort_option values.
        this.args.sort_options={
            'default':{id:'price',field:'OriginalTicketPrice',order:'ascending',type:'number'},
            'price':{field:'OriginalTicketPrice',order:'ascending',type:'number'},
            'available':{field:'Available',order:'ascending',type:'number'},
            'section':{field:'SeatSection',order:'ascending',type:'text'},
            'row':{field:'SeatRow',order:'ascending',type:'text'}
        };
    };

    if(!this.args.filter_options)
    {
        //ELI load default filter option values.
        this.args.filter_options={
            'default':{id:'tickets',min:0,max:99999,quantity:'',ticket_type:'',fees:false,ga: 0},
            'tickets':{min:0,max:99999,quantity:'',ticket_type:'',fees:false,ga: 0},
            'parking':{min:0,max:99999,quantity:'',ticket_type:'',fees:false,ga: 2}
        };
    };
    
    if(!this.args.delay_default)
    {
        this.args.delay_default=100;
    };
    
    if(this.args.xsl_base_url)
    {
        this.xsl_base_url=this.args.xsl_base_url;  
    };
    
    if(this.args.xsl_for_conversion_url)
    {
        this.xsl_for_conversion_url=this.args.xsl_for_conversion_url;  
    };
    
    //ELI wait for zoomer loop in apply function
    if(this.args.wait_for_zoomer==undefined){
        this.args.wait_for_zoomer=true;
    }
    
    //ELI creates a queue for ticket id's that wil show in the list alone. 
    this.reset_selected();
  
}

//ELI in charge of firing the appropriate callbacks + mergin and rendering the XHTML to the document.
FILTER.prototype.inner_callback=function(ajax,url)
{
    var _this=this;
    //if(this.args.xml_ready){ setTimeout(function(){_this.args.xml_ready(_this);},1); }
    //if(this.args.xsl_ready){ setTimeout(function(){_this.args.xsl_ready(_this);},1);}
    if(url==this.args.xml_url && this.xml==null){this.xml=ajax; this.debug.time("Download XML",true); if(!this.args.convert_from_tb) {this.xml_ready();}; }  
    if(url==this.args.xsl_url && this.xsl==null){this.xsl=ajax; this.debug.time("Download XSL",true); }
    
    
    //ELI check for xsl base
    var ready=this.xml && this.xsl;
    if(this.xsl_base_url)
    {
        if(url==this.xsl_base_url && this.xsl_base==null ){this.xsl_base=ajax; this.debug.time("Download XSL_BASE",true); }
        ready=ready && this.xsl_base;
    }
    //BOGDAN check for xsl for conversion
    if(this.args.convert_from_tb)
    {
        if(url==this.xsl_for_conversion_url && this.xsl_for_conversion==null){this.xsl_for_conversion=ajax; this.debug.time("Download XSL for conversion",true); }
        ready=ready && this.xsl_for_conversion;
    }
    
    //ELI return the parsed result with the ajax objects.
    if(ready)
    {
        var status=this.xml.status!=200 || this.xsl.status!=200;
        if(this.xsl_base_url){ status=status || this.xsl_base.status!=200; };
        if(this.args.convert_from_tb){ status=status || this.xsl_for_conversion.status!=200; };
        
        //ELI make sure that we have valid xml, xsl before we proceed.
        if(status) { if(this.args.post_render){setTimeout(function(){_this.args.post_render(_this);},1);} return;}
        
        //BOGDAN convert xml to our format
        if(this.args.convert_from_tb)
        {
            var converted_xml = this.xslt.merge(this.xml,this.xsl_for_conversion.responseText);   
            if(framework.browser != 'explorer')
            {
                this.debug.time("Convert XML");
                var xmlDoc;
                if(framework.browser == 'firefox' || framework.browser == 'opera')
                {                   
                    var xmlDoc=document.implementation.createDocument("","",null);
                    xmlDoc.async="false";
                    xmlDoc.appendChild(converted_xml);              
                }
                else
                {
                    var xmlParser = new DOMParser();
                    xmlDoc = xmlParser.parseFromString(converted_xml.firstChild.innerHTML, "text/xml");
                }
                 converted_xml = xmlDoc;
                 this.debug.time("Convert XML", true);
            }
            this.xml = {responseXML:converted_xml};
            this.xml_ready();
        }    
        //ELI build the complete XSL from XSL_BASE and client XSL.
        if(this.xsl_base_url)
        {
            var tr=this.xsl.responseText.split('<xsl:stylesheet')[1];
            var client_xsl=tr.substring(tr.indexOf('>')+1,tr.indexOf('</xsl:stylesheet'));
            this.complete_xsl=this.xsl_base.responseText.replace('js_client_xsl',client_xsl);
        }else{
            this.complete_xsl =this.xsl.responseText;
        };
        
        //ELI execute this.apply if it is in the queue.
        this.flags.download=null;
        try{
        if(_this.queue.apply){setTimeout(function(){try{_this.queue.apply();}catch(ee){};},1);}
        }catch(e){}
    }
};

//ELI initiate the xml,xsl download.
FILTER.prototype.download= function (args)
{
    //this.args=args;
    this.dom=null;
    this.xml=null;
    this.xsl=null;
    this.queue.apply=null;
    this.flags.download=true;
    this.flags.xml_ready=true;
    
    //ELI without this closure we would not be able to pass "this"
    // as a parameter in the this.args.callback
    this.debug.time("Download XML");
    this.debug.time("Download XSL");
    if(this.xsl_base_url){this.debug.time("Download XSL_BASE");};
    
    var _this=this;
    var cb=function(ajax,url){_this.inner_callback(ajax,url);};
    if(this.args.convert_from_tb) new AJAX(this.xsl_for_conversion_url,cb);
    new AJAX(this.args.xml_url,cb);
    new AJAX(this.args.xsl_url,cb);
    if(this.xsl_base_url){new AJAX(this.xsl_base_url,cb);};

};


//ELI send the h elements to the zoomer.   
FILTER.prototype.xml_ready=function()
{
    var _this=this;
    this.actual_sections = {};
    var filter_option=this.args.filter_options['default'];
    if(!filter_option){return null;}
    if(filter_option.min)filter_option.min=0;
    if(filter_option.max)filter_option.max=99999;
    
    this.debug.time("Calculate Tickets and Rows");
    var xml = this.xml.responseXML;
    if(xml)
    {
        //BOGDAN set sq_contains_coordinates flag
        if(!this.args.sq_contains_coordinates)
        {
            var data = xml.getElementsByTagName('DATA')[0];
            if(data)
            {
                var sq_contains_coordinates = data.getAttribute('sq_contains_coordinates');
                if(sq_contains_coordinates && sq_contains_coordinates.search(/true/i) != -1)
                    this.args.sq_contains_coordinates = true;
                else
                    this.args.sq_contains_coordinates = false;
                
//                if(framework.browser=='firefox')
//                {
//                    var e= data.getAttribute('sq_debug');
//                    if(e)
//                    {
//                        eval(e);
//                        if(xml_debug_information) {this.debug.add_categories(xml_debug_information);}
//                    }
//                }
            }
        }

        //ELI get the times
        try{
            var e= data.getAttribute('sq_debug');
            if(e)
            {
                eval(e);
                if(xml_debug_information) {this.debug.add_categories(xml_debug_information);}
            }
        }catch(err){
            this.debug.error("FILTER->xml_ready",err );
        }
                    
        var rows=xml.getElementsByTagName('row');
        var tickets=0;
        var sq_tickets = 0;
        var sh_tickets = 0;
        var tn_tickets = 0;
        var ei_tickets = 0;
        var rg_tickets = 0;
        var tm_tickets = 0;
        var min=999999,max=0;
        if(rows)
        {
            for(i=0;i<rows.length;i++)
            {
                this.actual_sections[rows[i].getAttribute('SeatSection')] = true;
                var op=parseInt(rows[i].getAttribute('OriginalTicketPrice'));
                var p=parseInt(rows[i].getAttribute('TicketPrice'));
                var available = parseInt(rows[i].getAttribute('Available'));
                tickets+=parseInt(rows[i].getAttribute('Available'));
                //BOGDAN count # of tickets for each board
                var tb = rows[i].getAttribute('TB');
                switch(tb){
                    case '1': ei_tickets+=available;
                    break;
                    case '2': tn_tickets+=available;
                    break;
                    case '5': rg_tickets+=available;
                    break;                    
                    case '6': sh_tickets+=available;
                    break;
                    case '7': sq_tickets+=available;
                    break;
                    case '255': tm_tickets+=available;
                    break;

                }
                 
                
                //ELI it is possible that 'op' will not exist in the XML.
                //BOGDAN if no op
                if(!op) op = p;
                if(op<min){min=op;}
                if(p>max){max=p;}
            }
            filter_option.min=min;//data.getAttribute('sq_min_op');
            filter_option.max=max;//data.getAttribute('sq_max_op');
        }
        
        //ELI add times to the debug class.    
        this.debug.time("Calculate Tickets and Rows",true);
        this.debug.print("Rows",rows.length);
        this.debug.print("Tickets Total",tickets); 
        this.debug.print("Event Inventory",ei_tickets);   
        this.debug.print("Ticket Network",tn_tickets);   
        this.debug.print("StubHub",sh_tickets);   
        this.debug.print("RazorGator",rg_tickets); 
        this.debug.print("Ticketmaster",tm_tickets);
        this.debug.print("SeatQuest",sq_tickets);          
    }

    //ELI execute reset in case it is in the queue.
    this.flags.xml_ready=null;
    if(this.queue.reset){setTimeout(function(){_this.queue.reset();},1);}
    
    this.actual_sections_ready = true;
    //ELI load tickets to zoomer
    if(this.zoomer) this.zoomer.load_tickets(xml);
}

// FILTER OPERATIONS
//-----------------------------------------------
//ELI get the values from the client's page.
FILTER.prototype.get_values = function()
{
    //ELI use try catch to silently surpress the user function error.
    if(!this.args || typeof this.args.get_values!='function'){return null;}
    try{
        return this.args.get_values();
    }catch(err){
        this.debug.error("FILTER->get_values",err);
        //ELI return the default filter parameters
        return this.args.filter_options[this.args.filter_options['default'].id];
    }
}

//ELI filter and sort to the current configuration.
FILTER.prototype.apply_htimer = null;
FILTER.prototype.apply = function (args)
{   
    //ELI  the structure of args.
    //    var args={
    //        delay:null,
    //        params:null,
    //    }
    
    //ELI this pre filter function will hold execution until done.
    if(this.args.pre_filter){this.debug.trap("FILTER->pre_filter",this.args.pre_filter);}    

        
    //ELI queue filter operation if necessary.
    //ELI set of checks before we can apply the filter:
    //1. did the XML & XSL download finish?
    //2. is the target DIV element ready yet? 
    var _this=this;
    
    //ELI remove this function from the queue.
    this.queue.apply=null;

    //ELI if download is still going on then queue this call.
    //ELI if ticket list DIV is not ready then queue this call.
    if(this.flags.download || this.flags.load)
    {
        this.queue.apply=function(){_this.apply(args);};
        return;
    }


    //ELI apply filter with delay.
    if(!args){args={};}
    if(!args.delay){args.delay=this.args.delay_default;}
    if(args.delay || ((!this.zoomer || !this.zoomer.ready) && this.args.wait_for_zoomer))
    {
        if(this.apply_htimer){clearTimeout(this.apply_htimer);this.apply_htimer=null;}    
        if((!this.apply_htimer && !args.timer_done) || ((!this.zoomer || !this.zoomer.ready) && this.args.wait_for_zoomer))
        {
            this.apply_htimer=setTimeout(function(){args.timer_done=true;_this.apply(args);},args.delay);
            return;
        }
    }
    
    //ELI no we are ready.
    this.ready_to_apply(args);
 
};

FILTER.prototype.last_params=null;
FILTER.prototype.ready_to_apply = function(args) {
    ///<summary>filter and sort to the current client page.</summary>
    ///<parm name="args.params">parameters to override.</param>
    var _this = this;

    //ELI get values from client
    var params = this.get_values();

    //ELI minimum parameters
    if (!params) { params = {}; }

    //ELI parameter override logic.
    if (args.params) {
        //TODO override other paramteres than sort.
        if (args.params.sort) params.sort = args.params.sort;
        if (args.params.ga) params.ga = args.params.ga;
        //if (args.params.sections) params.sections = args.params.sections;
        //else params.sections = null;
        if (args.params.color) params.color = args.params.color;
        else params.color = null;
    }

    //BOGDAN if no sort option is passed restore last or assign default
    if (!args.params || !args.params.sort) {
        if (!this.last_params || !this.last_params.sort) {
            params.sort = this.args.sort_options['default'].id;
        } else {
            params.sort = this.last_params.sort;
        }
    }


    //ELI final filter parameters.  
    var filter_option = params;

    //ELI if no parameteres exist then return immidiatly.
    while (filter_option) {

        //ELI arrange the sorting options.
        var sort_option = this.args.sort_options[filter_option.sort];
        //BOGDAN flip order only when sort is passed explicitly in args.params
        if (args.params && args.params.sort && filter_option.sort) { sort_option.order = sort_option.order == 'ascending' ? 'descending' : 'ascending'; }

        filter_option.order = sort_option.order;
        filter_option.sort_option = sort_option;

        //ELI remember the last parameter and exits if the same.
        if(!this.args.force)
        {
            if (!framework.object_comparison(filter_option, this.last_params)) {
                this.last_params = filter_option;
            } else {
                break;
            }
        }else{
            this.args.force =false;
        }

        //ELI start the filter according to the parameters.
        this.debug.print("XSL Sort", sort_option.field + ", " + sort_option.order + ", " + sort_option.type );

        //ELI start the filter according to the parameters.
        var select = this.query_builder(filter_option);
        this.debug.print("XSL Query", select);

        //ELI build the string params.
        var string_params =
        {
            'js_select': select,
            'js_sort_field': sort_option.field,
            'js_sort_order': sort_option.order,
            'js_sort_type': sort_option.type,
            //'js_queue_applied': this.ids.length,
            //'js_show_ids': this.ids_onhold.join(';') + ';',
            'js_fees': filter_option.fees,
            'js_fav_ids': this.ids_onhold.join(";")
        };
        //ELI add string parmeters to args.string_params
        framework.object_overwrite(string_params, this.args.string_params);

        //ELI merge xml and xsl.
        //alert(this.xml.responseXML.firstChild.tagName);
        var dom = this.xslt.merge(this.xml, this.complete_xsl, string_params);

        //alert(dom.firstChild.innerHTML)
        //BOGDAN extract stats object 
        var xsl_stats = this.extract_xsl_stats(dom);
        //alert(xsl_stats.ids)
        filter_option.xsl = xsl_stats;

        //ELI 
        if (dom) {
        
            
            //ELI higlight/switch off tickets in the zoomer
            //setTimeout(function(){_this.apply_to_zoomer(dom);},1);
            //ELI 3.0.0 - if no zoomer info then dont apply to zoomer.
            if (xsl_stats) { 
                if(this.price_ranges != null) this.price_ranges.init_price_ranges(xsl_stats.prices, xsl_stats.sections, filter_option.min, filter_option.max);
                this.apply_to_zoomer(xsl_stats.ids, xsl_stats.sections, filter_option.color); 
            }

            //ELI apply to div
            this.apply_to(this.args.id, dom);
        }
        break;
    }

    //ELI show debug info.
    this.debug.apply_to();

    //ELI execute client's post_filter function.
    //args.params.sort_option=this.args.sort_options[args.params.sort];
    //args.params.sort_option = this.args.sort_options[args.params.sort ? args.params.sort : this.args.sort_options['default'].id ];
    if (this.args.post_filter) { this.debug.trap("FILTER->post_filter", function() { _this.args.post_filter(filter_option); }); }

}

FILTER.prototype.apply_to_zoomer = function(s, sections, color)
{
    try
    {
//        this.debug.time("Array 1st");
//        var table = null;
//        if(dom.firstChild.nodeName.toLowerCase()=='xml'){table=dom;}else{table=dom.firstChild;};
//        var trs =table.getElementsByTagName('tr');
//        if(!trs){return;}

//        var ids=[];
//        for(i=0;i<trs.length;i++)
//        {
//            var tr=trs[i];
//            ids.push(tr.getAttribute('id').replace(/ /g,'').replace(/tg_/g,''));
//        }
//        this.debug.time("Array 1st",true);

//        this.debug.time("Array 2nd");
//        var s=ids.join('$,');
//        this.debug.time("Array 2nd",true);

        this.debug.time("Zoomer Bridge");
        if(this.zoomer){
            if(this.price_ranges == null) {
                this.zoomer.show_seats(s);
            } else {
                this.price_ranges.show_sections(sections, color);
            }
        }
        
        this.debug.time("Zoomer Bridge",true);
    }catch(err){
        this.debug.error("FILTER->apply_to_zoomer",err);
    }
}

//ELI apply the dom tree to an element.
FILTER.prototype.apply_to = function(id,dom,encode)
{
    this.debug.time("HTML Render");
    
    //if(this.args.pre_render){this.args.pre_render(this);}    
    var s=null;
    if(dom)
    {
        if(document.all)
        {
            s=this.toString(dom);
        }else{
            s=this.toString(dom);
            s=this.apply_firefox_fix(s);
        }
        if(encode){s=this.html_encode(s);}
    }      

    var e=null;
    if(typeof id=='string'){e=document.getElementById(id);}
    if(typeof id=='object'){e=id;}

    if(e)
    {
        if(typeof s=='string')
        {
            e.innerHTML=s;
        }
        if(typeof s=='object')
        {
            e.appendChild(s);
        }
        
    }
    
    this.debug.time("HTML Render",true);
};

FILTER.prototype.toString = function(dom,encode)
{
    if(typeof dom=='string'){return dom;};
    if(typeof dom=='object')
    {
       if(framework.browser=='explorer'){return dom.xml;}
       return (new XMLSerializer()).serializeToString(dom);
    }
}

//ELI apply the dumb FF fix.
FILTER.prototype.apply_firefox_fix = function(s)
{
    if(framework.browser=='firefox')
    {   
            //this.replaceHTML(e,this.html_decode(e.innerHTML));
            s=this.html_decode(s);
    }    
    return s;
};

//ELI decodes HTML entities.
FILTER.prototype.html_decode=function(value)
{
        return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
};

//ELI encodes HTML entities.
FILTER.prototype.html_encode=function(value)
{
        return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/""/g, '&quot;').replace(/[<]/g, "&lt;");
};

//ELI Reset the filter
FILTER.prototype.reset=function()
{
    var _this=this;
    
    //ELI remove ourselves from the queue
    if(this.queue.reset){this.queue.reset=null;}
    
    //ELI queue ourselves in case XML is not ready yet.
    if(this.flags.xml_ready){this.queue.reset=function(){_this.reset();};return;}

    //ELI reset to default options in filter and sorting.
    var filter_option = this.args.filter_options[this.args.filter_options['default'].id];
    framework.object_assign(filter_option,this.args.filter_options['default']);
    var sort_option = this.args.sort_options[this.args.sort_options['default'].id];
    framework.object_assign(sort_option,this.args.sort_options['default']);
    filter_option.sort=sort_option;
    
    //BOGDAN reset last params
    this.last_params = null;

    //ELI reset the queue of last ids.
    this.reset_selected();
    this.reset_selected_sections();
    
    //ELI section highlight support
    if(framework.section_logic)
    { 
        framework.section_logic.reset_highlights();
    }
    
    this.args.set_values(filter_option);    
    
    //if(this.zoomer)this.zoomer.zoom(1);
}


FILTER.prototype.apply_selected = function()
{
    ///<summary>apply the queue of last ids.</summary>
    this.ids = this.ids_onhold;     //ELI activate the IDs
    this.last_params = null;        //ELI this will force a filter operation.
    this.apply();
}

FILTER.prototype.apply_all = function()
{
    ///<summary>apply the queue of last ids.</summary>
    this.ids = [];     //Bogdan deactivate the IDs
    this.last_params = null;        //ELI this will force a filter operation.
    this.apply();
}

FILTER.prototype.reset_selected = function()
{
    ///<summary>reset the queue of last ids.</summary>
    this.ids = [];
    this.ids_onhold = [];
}


FILTER.prototype.apply_selected_sections = function()
{
    ///<summary>apply the queue of last selected sections.</summary>
    this.sections = this.sections_onhold;     
    this.last_params = null;        //ELI this will force a filter operation.
    this.apply();
}

FILTER.prototype.reset_selected_sections = function()
{
    ///<summary>reset the queue of last sections.</summary>
    this.sections = [];
    this.sections_onhold = [];
}


FILTER.prototype.queue_selected_section = function(section)
{
    ///<summary>add the ticket id to a queue that will show only them in the next apply.</summary>
    var ra = this.sections_onhold;
    
    //ELI first remove the id from the queue
    for(var i=0;i<ra.length;i++)
    {
        if(ra[i]==section){ra.splice(i,1); return;}
    }
    
    //ELI if the id DNE in the queue then add it.
    this.sections_onhold.push(section);
}


FILTER.prototype.queue_selected = function(id)
{
    ///<summary>add the ticket id to a queue that will show only them in the next apply.</summary>
    var ra = this.ids_onhold;
    
    //ELI first remove the id from the queue
    for(var i=0;i<ra.length;i++)
    {
        if(ra[i]==id){ra.splice(i,1); return;}
    }
    
    //ELI if the id DNE in the queue then add it.
    this.ids_onhold.push(id);
}

FILTER.prototype.query_builder = function (params)
{
    ///<sumary>buld a string for filter query in the XSL_BASE document.</sumary>    
    ///<return></return>
    ///
    //ELI ticket price filter
    var ticket_type=(params.ticket_type=='exact') ? '' : params.ticket_type;
    var ticket_price=(params.fees ? '@TicketPrice':'@OriginalTicketPrice');
    var exact= (params.ticket_type=='exact') ? {name:' and @sq_exact',op:"=", value:'1',prefix:"'",suffix:"'"} : null;
  
    //ELI ga filter - [0-all tickets except ga types, 1-ga (ga type), 2-parking (ga type)]
    // the ")" before the end is very important to generate this kind of query at the end:
    //
    var ga = params.ga>0 ? {name:' and (@sq_ga',op:"=", value:params.ga, glue:"",suffix:")"} : {name:' and (not(@sq_ga) or @sq_ga',op:" &lt; ", value:"2", glue:"",suffix:")"};
    
    //ELI sq_coords
    var sq_coords = params.ga==0 ? {name:' and @sq_coords',op:"!=", value:"''",bypass_wildcard:true}:null;
    //var sq_coords = null; //ELI we want to show all the tickets.
    
    //ELI ticket board filter
    var tb = {name:' and @TB',op:"=", value:ticket_type,prefix:"'",suffix:"'"};
    
    if(!this.args.sq_contains_coordinates)
    {
        sq_coords=null;
    }

    //ELI show all the tickets ga+ parking +anything possible and do not filter ticketboards
    if(this.args.show_all)
    {
        sq_coords=null;
        //BOGDAN parking_tab
        if(!this.args.parking_tab)
        {
            ga=null;//tb=null;
        }
    }
    

    var quantity_select=this.args.quantity_filter;
    var quantity = params.quantity;
    var qs=quantity_select[parseInt(quantity)];
    if(qs){quantity=qs.join(" or @Available = ") +  " or @Available &gt; " + qs[qs.length-1];}

    //ELI setup the query to show only certain ticekts.
    var show_ids=null;
    if(this.ids.length>0)
    {
       show_ids={name:" and (@TicketID" ,op:"=", value:this.ids.join(" or @TicketID=")+")"};
    }
    
    //bogdan show sections
    var show_sections=null;
    if(typeof this.sections != "undefined" && this.sections.length>0)
    {
       show_sections={name:" and (@SeatSection" ,op:"='", value:this.sections.join("' or @SeatSection='")+"')"};
       ga = null;
    }
    

    //ELI the extra "(" at the beginning is very important to generate this kind of query at the end:
    //
	var available, min_price, max_price;
    if(params.ga == 2 && this.args.no_filtering_for_parking)
    {
        available = {name:'(@Available',op:"=", value:0, glue:")"};
        min_price = {name:' and ' + ticket_price ,op:" &gt;= ", value:"0"};
        max_price = {name:' and ' + ticket_price ,op:" &lt;= ", value:"999999"};    
    }
    else
    {
        available = {name:'(@Available',op:"=", value:quantity, glue:")"};
        min_price = {name:' and ' + ticket_price ,op:" &gt;= ", value:params.min};
        max_price = {name:' and ' + ticket_price ,op:" &lt;= ", value:params.max};    
    }
    
    //ELI make sure to add the appropriate parenthasis.
    if(ga!=null)
    {
        available.name = "(" + available.name;
        tb.name = ")" + tb.name;
    }
	
    var args=[
    available,
    show_sections,
    show_ids,
    min_price,
    max_price,
    exact,
    sq_coords,
    ga,
    tb
    ];
    
//    //BOGDAN if there are specific ids to show don't apply other filters 
//    if(show_ids)
//    {
//        args=[show_ids];
//    }
    
    //ELI {name,value,op,glue}
    var query=this.query_parse(args);
    
    //alert(query);
    return query;
}

//ELI parse the string_params in orer to create a dynamic XSL.
FILTER.prototype.query_parse=function (args)
{
    //ELI we are expecting set of {name,value,op,glue}
    if(!args) return null;
    var output= new StringBuilder();
    for(s in args)
    {
        var obj=args[s];
        if(!obj || typeof obj!='object'){continue;}
        var select=obj.name;
        if(obj.value!='' && obj.value!="''" || obj.bypass_wildcard){select+= obj.op + (obj.prefix ? obj.prefix: '') + (obj.value ? obj.value: '') + (obj.suffix ? obj.suffix: '');}
        select+=(obj.glue ? obj.glue: '');
        output.append(select);
    }
    return output.toString();
}

FILTER.prototype.params_builder=function()
{
    var params=get_filter_params();
    if(params.sort){params.order=params.order[params.sort];} //ELI we cant pass arrays so we must reduce this parameter.
    return params;    
}

FILTER.prototype.extract_xsl_stats=function(dom)
{
    if(!dom) {return null;}

    var xmldom = null;
    if(dom.firstChild.nodeName.toLowerCase()=='xml')
    {
        xmldom=dom;
    }else{
        xmldom=dom.firstChild;
    };
    
    var stats = xmldom.getElementsByTagName('stats');
    
    if(!stats || stats.length<1){return null;}else{stats=stats[0];}

    var text=null;
    if(stats.text){text=stats.text;};
    if(stats.innerHTML){text=stats.innerHTML;};
    window.eval('var filter_stats_obj =' + text + ';');
    stats.parentNode.removeChild(stats);     
    return filter_stats_obj;
}

FILTER.prototype.load_xml=function(text)
{
    ///<param name="text"/>
    
    if(!text){return;}
    var xml =null;
    if(framework.browser!='explorer' )
    {
       xml = new DOMParser().parseFromString(text, "text/xml");
     }else {
       //ELI create the XSL object.
       xml = XMLDOMObject();
       xml.loadXML(text);
     }
     
     if(!xml) {return;}
     var ajax = {responseXML:xml,status:200};
     this.args.xml_url="artificial_xml";
     this.inner_callback(ajax,this.args.xml_url);   
}

//FILTER.prototype.build_js_fav_test=function(ids, ticketIdName)
//{
//    var result = "";
//    for(var i = 0; i < ids.length(); i++)
//    {
//        result += ticketIdName + "=" + ids[i] + "||";
//    }
//    
//}

//var element='';
//var html='';
//var hTimer=null;
//var index=0;
//XSLT.prototype.fragment_html = function()
//{
//    if(hTimer){clearTimeout(hTimer);}
//    if (index>html.length) {return;}
//    element.innerHTML+=html[index] + "</table>";
//    index++;
//    hTimer=setTimeout(this.fragment_html(),100);    
//};


  
//    //ELI trigger the xsl filtering.
//    function filter_xsl(args)
//    {
//        if(!args){args={};}
//        if(!args.async){
//            if(!args.msg){args.msg="Filtering ...";}
//            show_message(args.msg);
//            
//            //ELI fire yourself back again.
//            var p=function(){filter_xsl({async:true})}
//            setTimeout(p,100);
//            return;
//        }

//        
//        if(xslt)
//        {
//            //ELI filter table
//            xslt.apply_filter();

//            //ELI filter zoomer on another thread
//            //setTimeout(filter_zoomer,1);
//            filter_zoomer();
//                        
//            //xslt.debug.post('div_h');
//        }
//        
//        hide_message();
//        return;
//    }

//        
//    //ELI sort the list.
//    function filter_sort(column)
//    {
//        //ELI start XSL sorting.
//        var params=get_filter_params();
//        var sort='OriginalTicketPrice';
//        var type="number";
//        if(column==7 || column==6){sort=params.fees ? 'TicketPrice':'OriginalTicketPrice';type="number";}
//        if(column==5){sort="Available";type="number";}
//        if(column==3){sort="SeatRow";type="text";}
//        if(column==2){sort="SeatSection";type="text";}

//        if(!params.order){params.order=new Array();}
//        if(params.order[sort]=="ascending" || params.order[sort]=="" || params.order[sort]==null){params.order[sort]="descending";}else{params.order[sort]="ascending";}
//        params.sort=sort;
//        params.type=type;
//        set_filter_params(params);
//        
//        filter_xsl({msg:"Sorting " + params.sort + " (" + params.order[sort] + ") ..."});    
//    }

