/**
 * Filter criteria widget
 */
jQuery.fn.filterCriteria = function(s) {
  var settings = jQuery.extend({
    'pre_select_filter_id' : null, 
    'options' : null, 
    'criterions' : null, 
    'submit_as' : 'filter', 
    'user_filter' : null, 
    'data' : null, 
    'can_add_filter' : true,
    'on_show_results' : null, 
    'on_result_links' : null, 
    'new_filter_url' : null
  }, s);
  
  return this.each(function() {
    var wrapper = $(this);
    var wrapper_id = wrapper.attr('id');
    
    var form = wrapper.find('form');
    
    var form_head = form.find('div.filter_criteria_head');
    var form_body = form.find('div.filter_criteria_body');
    
    var options_wrapper = form_head.find('div.filter_criteria_options');
    var results_wrapper = wrapper.find('div.filter_results');
    
    // ---------------------------------------------------
    //  Helper methods
    // ---------------------------------------------------
    
    /**
     * Display criterions form
     * 
     * @param Function callback
     */
    var show_criterions_form = function(callback) {
      if(form.is('form.expanded')) {
        if(typeof(callback) == 'function') {
          callback.apply(form[0]);
        } // if
      } else {
        form_body.slideDown(function() {
          form.addClass('expanded');
          
          if(typeof(callback) == 'function') {
            callback.apply(form[0]);
          } // if
        });
      } // if
    }; // show_criterions_form
    
    /**
     * Hide criterions form
     * 
     * @param Function callback
     */
    var hide_criterions_form = function(callback) {
      if(form.is('form.expanded')) {
        form_body.slideUp(function() {
          form.removeClass('expanded');
          
          if(typeof(callback) == 'function') {
            callback.apply(form[0]);
          } // if
        });
      } else {
        if(typeof(callback) == 'function') {
          callback.apply(form[0]);
        } // if
      } // if
    }; // hide_criterions_form
    
    // Run button click (don't collapse / expand)
    var run_button = form.find('button[type=submit]').click(function(e) {
      e.stopPropagation();
    });
    
    /**
     * Block form while filter is being executed
     */
    var block_form = function() {
      App.Wireframe.PageTitle.setPrintUrl('');
      results_wrapper.empty().append('<img src="' + App.Wireframe.Utils.indicatorUrl() + '">').addClass('loading');
      form_head.find('select, input, button').prop('disabled', true);
    }; // block_form
    
    /**
     * Unblock form after filter has been executed
     */
    var unblock_form = function() {
      results_wrapper.empty().removeClass('loading');
      form_head.find('select, input, button').prop('disabled', false);
    }; // unblock_form
    
    /**
     * Cached saved filters option group reference
     */
    var saved_filters_group = false;
    
    /**
     * Return saved filters group
     * 
     * @return jQuery
     */
    var get_saved_filters_group = function() {
      if(saved_filters_group && saved_filters_group.length) {
        return saved_filters_group;
      } else {
        saved_filters_group = filter_picker.find('optgroup');
        
        if(saved_filters_group.length == 0) {
          filter_picker.append('<option value=""></option>');
          
          saved_filters_group = $('<optgroup label="' + App.lang('Saved Filters') + '"></optgroup>').appendTo(filter_picker);
        } // if
        
        return saved_filters_group;
      } // if
    }; // saved_filters_group
    
    // Cached ID of selected filter
    var selected_filter_id = 0;
    
    /**
     * Set specific filter as selected
     * 
     * @param Number filter_id
     * @param Boolean update_select
     */
    var select_filter = function(filter_id, update_select) {
      if(update_select && filter_picker.val() != filter_id) {
        filter_picker.val(filter_id);
      } // if
      
      if(filter_id == 0) {
        save_button.text(App.lang('Save'));

        if(!settings['new_filter_url']) {
          save_button.hide();
        } // if

        delete_button.hide();
      } else {
        var filter = get_filter(filter_id);
        
        if(typeof(filter) == 'object' && filter) {
          if(filter['permissions']['can_edit']) {
            save_button.show().text(App.lang('Save Changes'));
          } else {
            save_button.hide();
          } // if
          
          if(filter['permissions']['can_delete']) {
            delete_button.show();
          } else {
            delete_button.hide();
          } // if
          
          if(typeof(settings['options']) == 'object' && settings['options']) {
            for(var option in settings['options']) {
              options_wrapper.find('li[filter_option=' + option + '] input:checkbox')[0].checked = typeof(filter[option]) != 'undefined' && filter[option];
            } // for
          } // if
          
          if(typeof(settings['criterions']) == 'object' && settings['criterions']) {
            for(var criterion in settings['criterions']) {
              var row = form_body.find('tr.criterion_' + criterion);
              
              if(row.length) {
                var data_cell = row.find('td.report_select_data').empty(); // Empty data cell
                var selected_choice = typeof(filter[criterion]) != 'undefined' && filter[criterion] ? filter[criterion] : null;
                
                // Set and known criterion choice
                if(selected_choice && typeof(settings['criterions'][criterion]['choices'][selected_choice]) != 'undefined') {
                  row.find('td.report_select_select select').val(selected_choice);
                  
                  if(typeof(settings['criterions'][criterion]['choices'][selected_choice]) == 'object' && typeof(settings['criterions'][criterion]['choices'][selected_choice]['prepare']) == 'function') {
                    settings['criterions'][criterion]['choices'][selected_choice]['prepare'].apply(data_cell[0], [ settings['submit_as'], criterion, filter, settings['data'] ]);
                  } // if
                  
                // Unknwon choice, select first item
                } else {
                  var first_option = row.find('td.report_select_select select option:first');
                  
                  if(first_option.length > 0) {
                    first_option[0].selected = true;
                  } // if
                } // if
              } // if
            } // for
          } // if
        } else {
          App.Wireframe.Flash.error('Unknwon filter');
        } // if
      } // if
    }; // select_filter
    
    /**
     * Return filter details by filter ID
     * 
     * If filter with given ID is not found, function will return FALSE
     * 
     * @param Number filter_id
     * @return Object
     */
    var get_filter = function(filter_id) {
      for(var i in settings['filters']) {
        if(settings['filters'][i]['id'] == filter_id) {
          return settings['filters'][i];
        } // if
      } // for
      
      return false;
    }; // get_filter
    
    /**
     * Add new filter or update details of existing filter
     * 
     * @param Number filter_id
     * @param Object details
     */
    var set_filter = function(filter_id, details, is_new) {
      if(!settings['filters']) {
        settings['filters'] = [];
      } // if
      
      if(is_new) {
        settings['filters'].push(details);
      } else {
        for(var i in settings['filters']) {
          if(settings['filters'][i]['id'] == filter_id) {
            settings['filters'][i] = details;
            
            return;
          } // if
        } // for
        
        if(!added) {
          settings['filters'].push(details);
        } // if
      } // if
    }; // set_filter
    
    /**
     * Remove filter by ID
     * 
     * @param Number filter_id
     */
    var remove_filter = function(filter_id) {
      if(settings['filters']) {
        for(var i in settings['filters']) {
          if(settings['filters'][i]['id'] == filter_id) {
            if(settings['filters'][i]['id'] == filter_id) {
              settings['filters'].splice(i, 1);
            } // if
          } // if
        } // for
      } // if
      
      // Remove filter option
      filter_picker.find('option[value=' + filter_id + ']').remove();
      
      // Remove group if there are no other filters
      var group = get_saved_filters_group();
      
      if(group.find('option').length == 0) {
        group.prev().remove();
        group.remove();
        
        saved_filters_group = false;
      } // if
    }; // remove_filter
    
    // ---------------------------------------------------
    //  Prepare
    // ---------------------------------------------------
    
    // Expand / Collapse Body
    form_head.click(function() {
      if(form.is('form.expanded')) {
        hide_criterions_form();
      } else {
        show_criterions_form();
      } // if
    });
    
    // Initialize filter picker behavior
    var filter_picker = form_head.find('div.filter_criteria_picker select').change(function(e) {
      select_filter(filter_picker.val() == '' ? 0 : parseInt(filter_picker.val()), false);
    }).click(function(e) {
      e.stopPropagation(); // Don't bubble to criteria collapse / expand
    });
    
    // Initial set of filters
    if(typeof(settings['filters']) == 'object' && settings['filters']) {
      $.each(settings['filters'], function (index, filter) {
        get_saved_filters_group().append('<option value="' + filter['id'] + '">' + filter['name'].clean() + '</option>');
      });
    } // if
    
    // Prepare optiosn
    if(typeof(settings['options']) && settings['options']) {
      var options = '';
      for(var option in settings['options']) {
        if(typeof(settings['options'][option]) == 'object') {
          var option_label = settings['options'][option]['label'];
          var option_checked = typeof(settings['options'][option]['selected']) != 'undefined' && settings['options'][option]['selected'] ? 'checked="checked"' : '';
        } else {
          var option_label = settings['options'][option];
          var option_checked = '';
        } // if
        
        options += '<li filter_option="' + option + '"><input type="checkbox" name="' + settings['submit_as'] + '[' + option + ']" value="1" ' + option_checked + ' id="' + wrapper_id + '_options_' + option + '"> <label for="' + wrapper_id + '_options_' + option + '">' + option_label.clean() + '</label></li>';
      } // if
      
      options_wrapper.append('<ul>' + options + '</ul>').show();
      options_wrapper.find('ul li').click(function(e) {
        e.stopPropagation(); // Options should not toggle criterions form
      });
    } // if
    
    // Prepare criterions table, load and save of filters
    if(typeof(settings['criterions']) == 'object' && settings['criterions']) {
      var criterions_table = $('<table class="common" cellspacing="0">' + 
        '<tbody></tbody>' + 
        '<tfoot><tr><td></td><td colspan="2" class="filter_buttons">' + 
          '<button class="default" type="submit">' + App.lang('Run') + '</button> ' + 
          '<button class="filter_save_button" type="button">' + App.lang('Save') + '</button> ' + 
          '<button class="filter_delete_button" type="button">' + App.lang('Remove') + '</button> ' + 
        '</td></tr><tfoot>' + 
      '</table>').appendTo(form_body);
      
      criterions_table_body = criterions_table.find('tbody');
      criterions_table_foot = criterions_table.find('tfoot');
      
      // Prepare criterions
      for(var criterion in settings['criterions']) {
        var row = $('<tr class="report_select criterion_' + criterion + '">' + 
          '<td class="report_select_label">' + settings['criterions'][criterion]['label'].clean() + '</td>' + 
          '<td class="report_select_select"></td>' + 
          '<td class="report_select_data"></td>' + 
        '</tr>').appendTo(criterions_table);
        
        if(typeof(settings['criterions'][criterion]['choices']) == 'object' && settings['criterions'][criterion]['choices']) {
          var options = '';
          
          for(var choice in settings['criterions'][criterion]['choices']) {
            if(typeof(settings['criterions'][criterion]['choices'][choice]) == 'object') {
              var choice_label = settings['criterions'][criterion]['choices'][choice]['label'];
            } else {
              var choice_label = settings['criterions'][criterion]['choices'][choice];
            } // if
            
            options += '<option value="' + choice + '">' + choice_label.clean() + '</option>';
          } // for
          
          var select = $('<select name="' + settings['submit_as'] + '[' + criterion + ']" criterion="' + criterion + '">' + options + '</select>').appendTo(row.find('td.report_select_select'));
        } // if
      } // for
      
      criterions_table_body.find('tr.report_select').each(function() {
        var row = $(this);
        
        row.find('td.report_select_select select').change(function() {
          var select = $(this);
          
          var choice = select.val();
          var criterion = select.attr('criterion');
          
          var select_data_cell = row.find('td.report_select_data').empty();
          
          // If we have custom method for building filter value picker, execute it
          if(typeof(settings['criterions'][criterion]['choices'][choice]) == 'object' && typeof(settings['criterions'][criterion]['choices'][choice]['prepare']) == 'function') {
            settings['criterions'][criterion]['choices'][choice]['prepare'].apply(select_data_cell[0], [ settings['submit_as'], criterion, null, settings['data'] ]);
          } // if
        });
      });
      
      // Prepare update buttons
      var save_button = criterions_table_foot.find('td.filter_buttons button.filter_save_button').text(App.lang('Save As')).click(function() {
        var selected_filter_id = filter_picker.val();
        
        if(selected_filter_id && typeof(selected_filter_id) == 'string') {
          selected_filter_id = parseInt(selected_filter_id);
        } // if
        
        // Update existing filter
        if(selected_filter_id) {
          var filter = get_filter(selected_filter_id);
          
          var filter_name = prompt(App.lang('How would you like to name this filter? Leave unchanged to keep the existing name'), filter['name']);

		      if(filter_name !== null) {
			      filter_name = jQuery.trim(filter_name);
			
			      if(filter_name) {
	            $.ajax({
	              'url' : App.extendUrl(filter['urls']['edit'], { 'async' : 1 }), 
	              'type' : 'post', 
	              'data' : form.serialize() + '&submitted=submitted&filter[name]=' + filter_name,
	              'success' : function(response) {
	                if(typeof(response) == 'object') {
	                  if(response['name'] !== filter['name']) {
	                    filter_picker.find('option[value=' + filter['id'] + ']').text(response['name']);
	                  } // if

	                  set_filter(filter['id'], response);

	                  App.Wireframe.Flash.success('Selected filter has been updated');
	                } else {
	                  App.Wireframe.Flash.error('Failed to save filter. Please try again later');
	                } // if
	              }, 
	              'error' : function(response) {
	                App.Wireframe.Flash.error('Failed to save filter. Please try again later');
	              }
	            });
	          } else {
	            App.Wireframe.Flash.error('Filter name is required');
	          } // if
		      } // if
          
        // Create a new filter
        } else {
          var filter_name = prompt(App.lang('How would you like to name this filter?', ''));
          
          if(filter_name !== null) {
            filter_name = jQuery.trim(filter_name);
            
            if(filter_name) {
              if(settings['filters']) {

                var exists = false;
                $.each(settings['filters'], function (index, filter) {
                  if(filter['name'] == filter_name) {
                    exists = true;
                    return false;
                  } // if
                });

                if (exists) {
                  App.Wireframe.Flash.error('":name" already exists. Please use a different name', { 'name' : filter_name });
                  return false;
                } // if
              } // if

              $.ajax({
                'url' : App.extendUrl(settings['new_filter_url'], { 'async' : 1 }), 
                'type' : 'post', 
                'data' : form.serialize() + '&submitted=submitted&filter[name]=' + filter_name,
                'success' : function(response) {
                  if(typeof(response) == 'object') {
                    var group = get_saved_filters_group();
                    var option = $('<option value="' + response['id'] + '">').text(response['name']);

                    var option_added = false;
                    group.find('option').each(function() {
                      var current_option = $(this);

                      if(response['name'] < current_option.text()) {
                        current_option.before(option);
                        option_added = true;

                        return false;
                      } // if
                    });

                    // Not yet added? Add it to the end of the list
                    if(!option_added) {
                      group.append(option);
                    } // if

                    set_filter(response['id'], response, true);
                    select_filter(response['id'], true);
                    
                    App.Wireframe.Flash.success('Filter has been saved');
                  } else {
                    App.Wireframe.Flash.error('Failed to save filter. Please try again later');
                  } // if
                }, 
                'error' : function(response) {
                  App.Wireframe.Flash.error('Failed to save filter. Please try again later');
                }
              });
            } else {
              App.Wireframe.Flash.error('Filter name is required');
            } // if
          } // if
        } // if
        
      });
      
      var delete_button = criterions_table_foot.find('td.filter_buttons button.filter_delete_button').text(App.lang('Remove')).click(function() {
        var selected_filter_id = filter_picker.val();
        
        if(selected_filter_id && confirm(App.lang('Are you sure that you want to remove selected filter?'))) {
          selected_filter_id = parseInt(selected_filter_id);
          
          var filter = get_filter(selected_filter_id);
          
          if(typeof(filter) == 'object') {
            if(filter['permissions']['can_delete']) {
              $.ajax({
                'url' : App.extendUrl(filter['urls']['delete'], { 'async' : 1 }), 
                'type' : 'post', 
                'data' : {
                  'submitted' : 'submitted'
                },
                'success' : function(response) {
                  remove_filter(response['id']);
                  select_filter(0);
                  
                  App.Wireframe.Flash.success('Selected filter has been removed');
                }, 
                'error' : function(response) {
                  App.Wireframe.Flash.error('Failed to remove selected filter. Please try again later');
                }
              });
            } else {
              App.Wireframe.Flash.error(App.lang("You don't have permissions to delete this filter"));
            } // if
          } else {
            App.Wireframe.Flash.error(App.lang('Unknown filter'));
          } // if
        } // if
      }).hide();
      
      // Submit form
      form.submit(function(e) {
        hide_criterions_form(function() {
          var form_data = form.serialize(); // Get serialized form data before we block it (some checkboxes will be disabled, and therefore not submitted)
          
          block_form();
          
          $.ajax({
            'type' : 'get', 
            'url' : App.extendUrl(form.attr('action'), { 'async' : 1 }) + '&' + form_data, 
            'success' : function(response) {
              unblock_form();
              
              if(typeof(response) == 'object' && response) {
                App.Wireframe.PageTitle.setPrintUrl(App.extendUrl(form.attr('action'), { 'print' : 1 }) + '&' + form_data);
                
                if(typeof(settings['on_show_results']) == 'function') {
                  settings['on_show_results'].apply(results_wrapper[0], [ response, settings['data'], form.serializeArray() ]);
                  
                  if(typeof(settings['on_result_links']) == 'function') {
                    var result_links_wrapper = $('<div class="filter_result_links"></div>').appendTo(results_wrapper);
                    var links = [];
                    
                    settings['on_result_links'].apply(result_links_wrapper[0], [ response, settings['data'], links ]);
                    
                    if(links.length) {
                      var list = $('<ul></ul>').appendTo(result_links_wrapper);
                      
                      $.each(links, function(k, link) {
                        var list_item = $('<li><a href="' + App.extendUrl(link['url'], { 'async' : 1 }).clean() + '&' + form_data + '">' + link['text'].clean() + '</a></li>').appendTo(list);
                        
                        if(typeof(link['download']) != 'undefined' && link['download']) {
                          list_item.find('a').attr('target', '_blank');
                        } // if
                        
                        if(typeof(link['init']) == 'function') {
                          link['init'].apply(list_item.find('a')[0]);
                        } // if
                      });
                    } else {
                      result_links_wrapper.remove();
                    } // if
                  } // if
                } else {
                  results_wrapper.append('<p class="empty_page">' + App.lang('Filter returned results, but system is not able to display them') + '</p>');
                } // if
              } else {
                results_wrapper.append('<p class="empty_page">' + App.lang('Filter returned an empty result') + '</p>');
              } // if
            }, 
            'error' : function() {
              unblock_form();
              
              App.Wireframe.Flash.error('Failed to execute filter. Please try again later');
            }
          });
        });
        
        return false;
      });
      
      // Initialy hide footer if user can't create new filters
      if(!settings['can_add_filter']) {
        save_button.hide();
      } // if
    } // if
    
    // Pre-select filter
    if(settings['pre_select_filter_id']) {
      select_filter(settings['pre_select_filter_id'], true);
      form.submit();
    } // if
  });
};