var m_optionDefault = 'Tutti';
var m_currentURL = 'default';
var m_LoadFromSession = false;
var m_LastPage = 1;

var EventTypes = {
    FORM_LOADED: 1,
    RSET_LOADED: 2
};

/**
 * Costruttore
 * @param itemType Il tipo di elemento su cui deve essere fatta la query. 
 * Corrisponde al parametro del metodo DWRResultSetSrv.getResultSet
 * Corrisponde al parametro del metodo DWRFormSrv.getFormObject 
 * @param opts oggetto contenente proprietÃ  aggiuntive: 
 * 	'countMatches' (default: false): determina se debba essere attivato il conteggio dei record che 'matchano' i filtri
 * 	'profile' (default: false): se abilitato stampa nel log (console di firebug o alert) informazioni riguardo i tempi di esecuzione
 */
var Controller = function(itemType, opts) {
    this.init(itemType, opts);
};

Controller.prototype = {
    init: function(itemType, opts) {

        opts = opts || {
            countMatches: false,
            profile: false,
            debug: false,
            filterBoxId: 'filterBox',
            pageSize: -1,
            optionDefault: 'Tutte',
            currURL:  'default',
            renderCallback: function() {}
        };

        if (opts.currURL) {
            m_currentURL = opts.currURL;
        }

        DWRJSONSrv.getObject('myLastURL', function(lastURL) {
            if (lastURL == m_currentURL && m_currentURL != 'default') {
                m_LoadFromSession = true;

            } else {
                m_LoadFromSession = false;
                DWRJSONSrv.setObject('myLastURL', m_currentURL, function() {});
            }
        });

        DWRJSONSrv.getObject('myLastPage', function(lastPage) {
            if (lastPage != null)
                m_LastPage = lastPage;
        });
        
        this.itemType = itemType;
		
        this.countMatches = opts.countMatches || false;
        this.profile = opts.profile || false;
        this.pageSize = opts.pageSize || -1;
        m_optionDefault = opts.optionDefault || 'Tutte'; //***
        this.renderCallback = opts.renderCallback || (function() {});

        this.profileStartTime = 0;
		
        if(this.profile)
            Logger.addLogLevel(Logger.LOG_INFO);

        if(opts.debug)
            Logger.addLogLevel(Logger.LOG_DEBUG);
		
        this.view = new View();

        this.executeQuery();
        this.setupFilters(opts.filterBoxId);
        this.pager = new Pager(this.navBarClick, this);
    },

    /**
     * Esegue la query invocando il DWRResultSet e istanzia il ResultSet
     */
    executeQuery: function() {
        //ShowAjaxLoad();
        var that = this;

        var createRset = function(data) {
			
            if(data.errCode) {
                Logger.debug('DWRResultSetSrv - ' + data.errMg + '(' + data.errCode + ')');
		
            }
            else {
                Logger.debug('ECTRL: createRset');
                var res = {};
                //Deserializzazione del json restituito dal server
                eval('var results = ' + data);
                //Se il resultset e' composto da un solo elemento 'forzo' il formato
                if(!results.values.push) {
                    var record = results.values.value;
                    results.values = [record];
                }
                that.rset = new Resultset(results.keys, results.values);
                that.fireEvent(EventTypes.RSET_LOADED);
            }
        };

        //Esegue la chiamata Ajax
        DWRResultSetSrv.getResultSet(this.itemType, createRset);
    },

    navBarClick: function(el, type) {
        //ShowAjaxLoad();

        var update = false;
		
        switch(type) {
		
            case this.pager.FIRST_PAGE:
                if(!this.filteredRset.isFirstPage()) {
                    this.filteredRset.firstPage();
                    update = true;
                }
                break;

            case this.pager.PREVIOUS_PAGE:
                if(this.filteredRset.hasPreviousPages()) {
                    this.filteredRset.decPage();
                    update = true;
                }
                break;

            case this.pager.NEXT_PAGE:
                if(this.filteredRset.hasMorePages()) {
                    this.filteredRset.incPage();
                    update = true;
                }
                break;

            case this.pager.LAST_PAGE:
                if(!this.filteredRset.isLastPage()) {
                    this.filteredRset.lastPage();
                    update = true;
                }
                break;

            case this.pager.PAGE_NUMBER:
                var pn = parseInt(el.dom.innerHTML, 10);
                if( this.filteredRset.isValidPage(pn) && (pn != this.filteredRset.getCurrentPage()) ) {
                    this.filteredRset.gotoPage(pn);
                    update = true;
                }
                break;
        }
		
        if(update) {
            DWRJSONSrv.setObject('myLastPage', this.filteredRset.getCurrentPage(), function() {});
            this.showFilteredRset();
        }
		
        this.pager.update(this.filteredRset.getCurrentPage(), this.filteredRset.getTotalPages());
    },

    showFilteredRset: function() {
        Logger.debug('ECTRL: showFilteredRset');
        var contentBox = document.getElementById('contentBox');
        if(contentBox) {
            while(contentBox.firstChild)
                contentBox.removeChild(contentBox.firstChild);
        }
        //Render resultset
        while(this.filteredRset.next())
            this.view.renderHit(this.filteredRset);

        if(this.renderCallback){
            this.renderCallback();
        }

    //HideAjaxLoad();

    },

    renderRset: function() {
        Logger.debug('ECTRL: renderRset');
        this.profileStart();

        this.filteredRset = this.rset.applyFilters(FilterManager.getFilterGroups(), this.countMatches);

        this.filteredRset.applySecondPassFilters(FilterManager.getFilterGroups());
	
        if(this.countMatches) {
            FilterManager.updateMatches();
        }
		
        FilterManager.disableEmptyFilters();
        
        this.filteredRset.firstPage();
        this.filteredRset.setPageSize(this.pageSize);
        this.filteredRset.gotoPage(m_LastPage);
        this.pager.update(this.filteredRset.getCurrentPage(), this.filteredRset.getTotalPages());
        this.showFilteredRset();
		
        this.profileEnd();
		
        Logger.info(this.filteredRset.size() + ' elements');
		
    },
	
    renderRset2: function() {
        var pn = this.filteredRset.getCurrentPage();
        this.filteredRset.gotoPage(pn);
        this.showFilteredRset();
        this.pager.update(this.filteredRset.getCurrentPage(), this.filteredRset.getTotalPages());
    },
	
    /**
     * Istanzia i filtri e verifica lo stato
     */
    setupFilters: function(filterBoxId) {
        filterBoxId = filterBoxId || 'filterBox';
        var that = this;

        FilterManager.setupFilterStatus(this.itemType, function() {
			
            //Invoca il dwr e istanzia i filtri
            DWRFormSrv.getFormObject(this.itemType, function(json) {
                if(json.errCode) {
                    Logger.debug('DWRFormSrv - ' + json.errMsg + '(' + json.errCode + ')');
                }
                else {
                    //Deserializzo i filtri e creo l'html relativo
                    eval('var filters = ' + json + ';');
                    that.createFilterBox(filterBoxId, filters);
                    that.fireEvent(EventTypes.FORM_LOADED);
                }
            });
			
        }, this);

    },

    /**
     * Istanzia i filtri e crea il box di ricerca html
     */
    createFilterBox: function(filterBoxId, filters) {
		
        var filterBox = document.getElementById(filterBoxId);
		
        if(filterBox) {
            var numFilters = filters.length;
            var filterParent = Ext.DomHelper.append(filterBoxId, {
                tag: 'ul'
            });
            for(var i = 0; i < numFilters; i++) {
                var filter = filters[i];
                this.createFilterFragment(filter, filterParent);
            }
        }
    },
	
    /**
     * Crea l'html relativo ad un filtro
     */
    createFilterFragment: function(filter, filterParent) {

        var sliders = [];
        var filters = [];
        var filtersNode = [];
        var fieldName = filter.tpname;
        var fieldSubName = filter.tpsubname;
		
        //Crea il gruppo di filtri
        FilterManager.addFilterGroup(fieldName);

        switch(filter.style) {
            case HtmlFilters.SLIDER:

                var minValue = parseInt(filter.option.minvalue, 10);
                var maxValue = parseInt(filter.option.maxvalue, 10);
                var curMin = minValue;
                var curMax = maxValue;
                var filterCtrlId = fieldName;

                //Estraggo lo stato del filtro corrente
                var fStatus = FilterManager.getFilterStatus(filterCtrlId);

                if(fStatus != null) {
                    var pos = fStatus.indexOf(';');
                    if(pos > -1) {
                        curMin = parseInt(fStatus.substr(0, pos), 10);
                        curMax = parseInt(fStatus.substr(pos + 1), 10);
                    }
                }

                //Creo il filtro
                FilterManager.addFilter(fieldName, filterCtrlId, Operators.EQ, {
                    min: curMin,
                    max: curMax
                }, HtmlFilters.SLIDER);
				
                filtersNode.push({
                    tag: 'li',
                    cls: 'filter',
                    id: filterCtrlId + '_nod',
                    children: [
                    {
                        tag: 'div',
                        cls: 'filterCtrl left',
                        id: filterCtrlId,
                        children: [{
                            html: '<div id="handleMinValue" class="ui-slider-handle"></div><div id="handleMaxValue" class="ui-slider-handle" style="left:135px;"></div><div class="rangs"><span id="thumbMax" class="max slideing">1.000</span><span id="thumbMin" class="min slideing">0</span></div>'
                        }]
                    },
                    {
                        tag: 'div',
                        cls: 'filterCtrl left',
                        id: filterCtrlId + '_lbl',
                        style: 'padding-left: 63px;'
                    },
                    {
                        tag: 'div',
                        cls: 'clear',
                        html: ' '
                    }
                    ]
                });

                sliders.push({
                    id: filterCtrlId,
                    min: minValue,
                    max: maxValue,
                    curMin: curMin,
                    curMax: curMax
                });
				
                filters.push({
                    id: filterCtrlId,
                    type: filter.style
                });
                break;

            case HtmlFilters.CHECKBOX:
                //Creo un checkbox per ogni option definita nel filtro
                for(var i = 0; i < filter.option.length; i++) {

                    var option = filter.option[i];
                    var filterCtrlId = fieldName + '' + i;

                    //Estraggo lo stato del filtro corrente
                    var fStatus = FilterManager.getFilterStatus(filterCtrlId);

                    //Creo il filtro
                    FilterManager.addFilter(fieldName, filterCtrlId, Operators.EQ, option.value, HtmlFilters.CHECKBOX);

                    //Creo l'html
                    filterTag = {
                        tag: 'input',
                        type: 'checkbox',
                        id: filterCtrlId
                    };
                    if(fStatus != null)
                        filterTag.checked = 'checked';
					
                    filtersNode.push({
                        tag: 'li',
                        cls: 'filter',
                        children: [

                        {
                            tag: 'span',
                            cls: 'filterCtrl left',
                            children: [filterTag]
                        },

                        {
                            tag: 'span',
                            cls: 'filterLabel left dimension160' ,
                            children: [

                            {
                                tag: 'label',
                                'for': filterCtrlId,
                                id: filterCtrlId + '_lbl',
                                html: option.label
                            }
                            ]
                        },

                        {
                            tag: 'div',
                            cls: 'clear',
                            html: ' '
                        }
                        ]
                    });
					
                    filters.push({
                        id: filterCtrlId,
                        type: filter.style
                    });
                }
                break;
				
            case HtmlFilters.SUBFILTER:
                //Creo un checkbox e una lista di checkbox per ogni option definita nel filtro
                //fieldSubName
                //alert('Controller'+HtmlFilters.SUBFILTER);

                for(var i = 0; i < filter.option.length; i++) {

                    var option = filter.option[i];
                    var filterCtrlId = fieldName + '' + i;

                    //Estraggo lo stato del filtro corrente
                    var fStatus = FilterManager.getFilterStatus(filterCtrlId);

                    //Creo il filtro
                    FilterManager.addFilter(fieldName, filterCtrlId, Operators.EQ, option.value, HtmlFilters.SUBFILTER, fieldSubName, option.sublist);
                    
                    //Creo l'html
                    filterTag = {
                        tag: 'input',
                        type: 'checkbox',
                        id: filterCtrlId
                    };

                    if(fStatus != null) filterTag.checked = 'checked';

                    // ---------------------------------------------------
                    // <div id="accotype3_sub" class="filterCtrl">
                    //
                    // Sublist fragment
                    var suboptions = '';
                    if (option.sublist) {
                        if (option.sublist.length > 1) {
                            //Logger.debug('@@@@@@@@option.sublist - ' + option.sublist);

                            // Checkbox
                            suboptions = '<table class="checkcat"><tr>';
                            for(var ii = 0; ii < option.sublist.length; ii++) {
                                var subOption = option.sublist[ii];
                                suboptions = suboptions + '<td align="center"><input type="checkbox" id="'+filterCtrlId+'_'+subOption+'"/></td>';
                            }
                            suboptions = suboptions + '</tr><tr>';
                            // Labels
                            //Logger.debug('ECTRL: sublabels: '+option.sublabels);

                            if (option.sublabels) {
                                for(var is = 0; is < option.sublabels.length; is++) {
                                    var subLabel = option.sublabels[is];
                                    suboptions = suboptions + '<td align="center">'+subLabel+'</td>';
                                }
                            }
                            suboptions = suboptions +'<td align="center"><img border="0" src="'+option.subicon+'"/></td>';

                            suboptions = suboptions + '</tr></table>';
                        }
                    }
                    // ----------------------------------------------------

                    filtersNode.push(
                    {
                        tag: 'li',
                        cls: 'filter',
                        children: [ {
                            tag: 'span',
                            cls: 'filterCtrl left',
                            children: [filterTag]
                        },

                        {
                            tag: 'span',
                            cls: 'filterLabel left dimension160' ,
                            children: [{
                                tag: 'label',
                                'for': filterCtrlId,
                                id: filterCtrlId + '_lbl',
                                html: option.label
                            }]
                        },
                        {
                            tag: 'div',
                            cls: 'suboptions',
                            style: 'display: none;',
                            id: filterCtrlId+'_sub',
                            html: suboptions
                        },
                        {
                            tag: 'div',
                            cls: 'clear',
                            html: ' '
                        }
                        ]
                    });

                    filters.push({
                        id: filterCtrlId,
                        type: filter.style
                    });
                }
                break;

            case HtmlFilters.DROPDOWN:
                var options = [];
                var filterCtrlId = fieldName;
                var filterValues = [];

                var fStatus = FilterManager.getFilterStatus(filterCtrlId);

                options.push({
                    tag: 'option',
                    value: '',
                    html: m_optionDefault
                });

                for(var i = 0; i < filter.option.length; i++) {
                    var option = filter.option[i];
                    var optionTag = {
                        tag: 'option',
                        value: option.value,
                        html: option.label
                    };
                    if(fStatus == option.value)
                        optionTag.selected = 'select';
                    options.push(optionTag);
                    filterValues.push(option.value);
                }

                FilterManager.addFilter(fieldName, filterCtrlId, Operators.EQ, filterValues, HtmlFilters.DROPDOWN);
				
                filtersNode.push({
                    tag: 'li',
                    cls: 'filter',
                    children: [

                    {
                        tag: 'span',
                        cls: 'filterCtrl',
                        children: [

                        {
                            tag: 'select',
                            id: filterCtrlId,
                            children: options
                        }
                        ]
                    },

                    {
                        tag: 'span',
                        cls: 'filterLabel',
                        id: filterCtrlId + '_lbl',
                        html: ''
                    },

                    {
                        tag: 'div',
                        cls: 'clear',
                        html: ' '
                    }
                    ]
                });
				
                filters.push({
                    id: filterCtrlId,
                    type: filter.style
                });
                break;
				
            case HtmlFilters.TEXTBOX:
                var filterCtrlId = fieldName;
                var fStatus = FilterManager.getFilterStatus(filterCtrlId);
                FilterManager.addFilter(fieldName, filterCtrlId, Operators.LIKE, '', HtmlFilters.TEXTBOX);
				
                filtersNode.push({
                    tag: 'li',
                    cls: 'filter',
                    children: [

                    {
                        tag: 'span',
                        cls: 'filterCtrl',
                        children: [

                        {
                            tag: 'input',
                            type: 'text',
                            id: filterCtrlId,
                            value: fStatus
                        }
                        ]
                    },

                    {
                        tag: 'span',
                        cls: 'filterLabel',
                        id: filterCtrlId + '_lbl',
                        html: filter.label
                    },

                    {
                        tag: 'div',
                        cls: 'clear',
                        html: ' '
                    }
                    ]
                });
				
                filters.push({
                    id: filterCtrlId,
                    type: filter.style
                });
                break;
        }

        if(filters.length > 0) {
            //Creo l'html di tutti i filtri (vedi paragrafo 1.30.2 doc. tecnico)
            Ext.DomHelper.append(filterParent, {
                tag: 'li',
                children: [

                {
                    tag: 'ul',
                    cls: 'filterGroup',
                    children: [

                    {
                        tag: 'li',
                        cls: 'filterGroupLabel',
                        html: filter.label
                    },

                    {
                        tag: 'li',
                        children: [

                        {
                            tag: 'ul',
                            cls: 'filters',
                            children: filtersNode
                        }
                        ]
                    }
                    ]
                }
                ]
            });

            //<li class="slider-price">

            // <div class="rangs">
            //  <span class="max slideing">2.100€</span>
            //  <span class="min slideing">600€</span>
            //</div>


            for(var i = 0; i < sliders.length; i++) {
                var sliderDef = sliders[i];
                Logger.debug('@@@@@@@@@@######### Slider - ' + sliderDef.id + ' '+sliderDef.min+' ' + sliderDef.max + ' ' + sliderDef.curMin + ' '+sliderDef.curMax);
                jQuery("#"+sliderDef.id).slider({
                    range: true,
                    animate: false,
                    min: sliderDef.min,
                    max: sliderDef.max,
                    stepping: 1,
                    slide: function(event, ui) {
                       var thisHandle = jQuery(ui.handle);
                       var handleID = thisHandle.attr('id');
                       if (handleID == 'handleMinValue') {
                          minValue = ui.value;
                          Ext.get('thumbMin').update(minValue);
                       } else {
                          maxValue = ui.value;
                          Ext.get('thumbMax').update(maxValue);
                       }
                       return false;
                    },
                    change: function(event, ui) {
                        var thisHandle = jQuery(ui.handle);
                        var handleID = thisHandle.attr('id');

                        var group = FilterManager.getFilterGroup(sliderDef.id);
                        var filter = group.getFilter(sliderDef.id);


                        var minValue = filter.getMinValue();
                        var maxValue = filter.getMaxValue();

                        if (handleID == 'handleMinValue') {
                          minValue = ui.value;
                        } else {
                          maxValue = ui.value;
                        }
                        
                        FilterManager.setFilterStatus(sliderDef.id, minValue + ';' + maxValue);
                        FilterManager.setFilterValue(sliderDef.id, {min: minValue, max: maxValue });
                        ctrl.renderRset();


                    }
                });
                
            }

            for(var i = 0; i < filters.length; i++) {
                var ctrl = this;
                var filter = filters[i];
                this.toggleFilter(filter.id, filter.type);
            }

        }

    },
    toggleFilter: function(id, type) {

        var ctrl = this;
        var el = Ext.get(id);
        //Logger.debug('ECTRL: toggleFilter: ' + id + '=' +type);
        switch(type) {
            case HtmlFilters.CHECKBOX:
                el.on({
                    'click': function() {
                        if(this.checked) {
                            FilterManager.setFilterStatus(id, 1);
                            FilterManager.activateFilter(id);
                        }
                        else {
                            FilterManager.setFilterStatus(id, null);
                            FilterManager.deactivateFilter(id);
                        }
                        ctrl.renderRset();
                    }
                });
				
                if(el.dom.getAttribute('checked'))
                    FilterManager.activateFilter(id);
				
                break;

            case HtmlFilters.SUBFILTER:
                jQuery("#"+id+"_sub INPUT[type='checkbox']").click(function() {

                    // Sub Status
                    var selectedItems = new Array();
                    jQuery("#"+id+"_sub INPUT[type='checkbox']:checked").each(function() {
                        selectedItems.push(this.id);
                    });
                    FilterManager.setSelectedSubValue(id, selectedItems);
                    FilterManager.setFilterSubStatus(this.parentNode.id, this.id);
                    // Sub Status

                    Logger.debug('SUB input clicked - '+this.id + '-' +this.parentNode.id + ' - '+ selectedItems);

                    FilterManager.activateFilter(this.parentNode.id);
                    ctrl.renderRset();
                });

                el.on({
                    'click': function() {
                        var elJQ = jQuery('#'+id+'_sub');

                        // Ciclare su tutti i checkbox all'interno e quelli checkati aggiungerli al filtro
                        // quindi funzione setFilterSubStatus(id,1) se ttivo, setFilterSubStatus(id, null) se non attivo.


                        if(this.checked) {
                            if (elJQ) {
                                elJQ.show()
                            };

                            jQuery("#"+id+"_sub INPUT[type='checkbox']").attr('checked', true);

                            // Sub Status
                            var selectedItems = new Array();
                            jQuery("#"+id+"_sub INPUT[type='checkbox']:checked").each(function() {
                                selectedItems.push(this.id);
                            });
                            FilterManager.setSelectedSubValue(id, selectedItems);
                            FilterManager.setFilterSubStatus(this.parentNode.id, this.id);
                            // Sub Status

                            FilterManager.setFilterStatus(id, 1);
                            FilterManager.activateFilter(id);
                        }
                        else {
                            if (elJQ) {
                                elJQ.hide()
                            }

                            jQuery("#"+id+"_sub INPUT[type='checkbox']").attr('checked', false);

                            FilterManager.setSelectedSubValue(id, null);
                            FilterManager.setFilterSubStatus(this.parentNode.id, null);
                            FilterManager.setFilterStatus(id, null);
                            FilterManager.deactivateFilter(id);
                        }
                        ctrl.renderRset();
                    }
                });

                if(el.dom.getAttribute('checked'))
                    FilterManager.activateFilter(id);

                break;
				
            case HtmlFilters.DROPDOWN:
                el.on({
                    'change': {
                        fn: function() {
                            if(this.value != '') {
                                FilterManager.setFilterStatus(id, this.value);
                                FilterManager.setSelectedValue(id, this.value);
                                FilterManager.activateFilter(id);
                            }
                            else {
                                FilterManager.setFilterStatus(id, '');
                                FilterManager.deactivateFilter(id);
                            }
                            ctrl.renderRset();
                        }
                    }
                });

                var value = el.dom.getAttribute('value');
                if(value && value != '') {
                    FilterManager.setSelectedValue(id, value);
                    FilterManager.activateFilter(id);
                }
									
                break;
				
            case HtmlFilters.TEXTBOX:
                el.on({
                    'keyup': function() {
                        var activated = false;
                        var prevActive = FilterManager.isFilterActive(id);
                        if( (this.value != '') && (this.value.length > 2) ) {
                            FilterManager.setFilterStatus(id, this.value);
                            FilterManager.activateFilter(id);
                            FilterManager.setFilterValue(id, this.value);
                            activated = true;
                        }
                        else {
                            FilterManager.setFilterStatus(id, '');
                            FilterManager.deactivateFilter(id);
                        }
                        if(prevActive || activated)
                            ctrl.renderRset();
                    }
                });
				
                var value = el.dom.getAttribute('value');
                if(value && value.length > 2) {
                    FilterManager.setFilterValue(id, value);
                    FilterManager.activateFilter(id);
                }
				
                break;
        }
    },
    fireEvent: function(eventType) {
        switch(eventType) {
            case EventTypes.FORM_LOADED:
                this.formLoaded = true;
                break;
            case EventTypes.RSET_LOADED:
                this.rsetLoaded = true;
                break;
        }
        Logger.info('fireEvent: ' + this.formLoaded + this.rsetLoaded);
        if(this.formLoaded && this.rsetLoaded)
            this.renderRset();
    },
    profileStart: function() {
        this.profileStartTime = new Date().getTime();
    },
    profileEnd: function() {
        var totTime = new Date().getTime() - this.profileStartTime;
        Logger.info('Total time:: ' + totTime);
    }

};
