//
var $t_search_result;
var $t_search_result_filtered;
var SEARCH_SETTINGS = {};

function select_row(selector){
  $selector = $(selector);
  $selector.addClass('selected');
  $(':checkbox', $selector).attr('checked', 'checked');
}

function deselect_row(selector){
  $selector = $(selector);
  $selector.removeClass('selected');
  $(':checkbox', $selector).removeAttr('checked');
}

function reset_filters(){
  $('#filters > .filter-group > .filter-group-body > a').removeClass('selected');
}

function compute_filtered_result(){
  // SEARCH_SETTINGS outer dependency
  var start = new Date().getTime();
  if(SEARCH_SETTINGS.filters){
    reset_filters();
    var filter_params_array = SEARCH_SETTINGS.filters.split(';');
    for(var i = 0; i < filter_params_array.length; ++i){
      filter_params_array[i] = "#"+filter_params_array[i];
    }
    $(filter_params_array.join(','), $('#filters')).addClass('selected');
  }  
  
  $t_search_result_filtered = $t_search_result;
  var t_filters_array = [];
  // для каждой группы фильтров
  $('#filters > div.filter-group > div.filter-group-body').each(function(){
    var t_selector_array = [];
    $(this).find('a.selected').each(function(){       
      t_selector_array.push('.'+$(this).attr('id'));
    });
    if(t_selector_array.length > 0){
      $t_search_result_filtered = $t_search_result_filtered.filter(t_selector_array.join(','));
    }
  });
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("filter computed in "+executionTime+" milliseconds");}catch(e){}
}

function __select_rows(){
  var start = new Date().getTime();
  
  if(SEARCH_SETTINGS.select){
    var selected_rows_array = SEARCH_SETTINGS.select.split(';');
    for(var i = 0; i < selected_rows_array.length; ++i){
      selected_rows_array[i] = "#"+selected_rows_array[i];
    }
    $('#search-results > tbody > tr').each(function(){
      $(this).removeClass('selected');
      $(':checkbox', $(this)).removeAttr('checked');
    });
    
    $(selected_rows_array.join(','), $('#search-results > tbody')).each(function(){
      $(this).addClass('selected');
      $(':checkbox', $(this)).attr('checked', 'checked');
    });
    
  }  
  
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("select applied in "+executionTime+" milliseconds");}catch(e){}  
}

function __init_result_event_delegation(){
  $("#search-results .check_all, #search-results-dash .check_all").click(function(){
    select_row('#search-results > tbody > tr', true);
    return false;
  });

  $("#search-results .uncheck_all, #search-results-dash .uncheck_all").click(function(){
    deselect_row('#search-results > tbody > tr', true);
    return false;
  });

  $("#search-results > tbody").delegate(':checkbox', 'click', function(){ return false; });
  $("#search-results > tbody").delegate(':checkbox', 'mousedown', function(){
    
    $__this_row = $(this).closest('tr');
    
    if($(this).is(':checked')){
      //deselect_row($__this_row);
      $(this).removeAttr('checked');
    }else{ 
      //select_row($__this_row);
      $(this).attr('checked', 'checked');
    }
    
    var t_selected_rows_array = [];
    $("#search-results > tbody > tr:has(input:checked)").each(function(){
      t_selected_rows_array.push($(this).attr('id'));
    });
    
    $.address.parameter('select', t_selected_rows_array.join(';'));
    
  });
}

function __init_filter_event_delegation(){
  $('#filters').delegate('a', 'click', function(){ return false; });
  $('#filters').delegate('a', 'mousedown', function(){
    // toggle
    $target_link = $(this);
    if($target_link.is('.select-none')){
      $target_link.closest('.filter-group').find('.filter-group-body > a').removeClass('selected');
    }else if($target_link.is('.super-select-none')){
      reset_filters();
    }else{
      $target_link.toggleClass('selected');
    }    
    // recollect and address
    var t_filters_array = [];
    $('#filters > div.filter-group > div.filter-group-body > a.selected').each(function(){
      t_filters_array.push($(this).attr('id'));
    });
    $.address.parameter('filters', t_filters_array.join(';'));
  });
}

function __init_constructions_print_button(){
  $("#print").click(function(){
    var t_ids = [];
    $("#search-results > tbody > tr.selected").each(function(){
      t_ids.push($(this).attr('id').match(/\d+/));
    });
    //
    if(t_ids.length > 0){
      document.cookie = 'ids_for_print='+t_ids.join(' ')+'; path=/';
      //
      p_window = window.open('/'+LOCALE+'/constructions/print', 'print_'); // TODO: extract path
      if(window.focus){p_window.focus();}
      return false;
    }
  });
}
  
function build_constructions_dom(){
  var t_html = '';
  var start = new Date().getTime();
  $t_search_result = $();
  if(CONSTRUCTIONS && CONSTRUCTIONS.length > 0){
    for(var i = 0; i < CONSTRUCTIONS.length; ++i){ 
      // TODO: refactor styling with classes
      t_html += '<tr id="'+CONSTRUCTIONS[i].p[0]+'" class="'+CONSTRUCTIONS[i].p[1]+'">';
      // 1
      t_html += '<td><input type="checkbox" id="check_'+CONSTRUCTIONS[i].p[0]+'"></td>';
      // 2
      t_html += '<td><div class="pica strong">'+CONSTRUCTIONS[i].p[2][1]+'</div><div class="sort hidden">'+CONSTRUCTIONS[i].p[2][0]+'</div>';
      t_html += '<div>'+STAGES[CONSTRUCTIONS[i].p[6]]+'</div><div class="gray-9">'+SOURCES[CONSTRUCTIONS[i].p[5]]+'</div></td>';
      // 3
      t_html += '<td>';
      if(CONSTRUCTIONS[i].p[3] === true){ t_html += '<div class="sprite-asterisk" title="'+COMMON.construction_new+'"></div>'; }
      if(CONSTRUCTIONS[i].a && CONSTRUCTIONS[i].a[0] === true){ t_html += '<div class="sprite-printer" title="'+COMMON.construction_print+'"></div>'; }
      if(CONSTRUCTIONS[i].c && CONSTRUCTIONS[i].c[0] === true){ t_html += '<div class="sprite-light-bulb" title="'+COMMON.construction_big+'"></div>'; }
      t_html += '</td>';
      // 4.1
      t_html += '<td><div>';
      if(VERBOSE < 3){
        t_html += '<a href="'+LOCALE+'/constructions/'+CONSTRUCTIONS[i].p[0]+'/edit" class="main-link construction">'+CONSTRUCTIONS[i].c[1]+'</a><a href="'+LOCALE+'/constructions/'+CONSTRUCTIONS[i].p[0]+'/edit" target="_blank" class="no-decor"><div class="sprite-external-small">&nbsp;</div></a>';
      }else if(VERBOSE == 3){
        t_html += '<a href="'+LOCALE+'/constructions/'+CONSTRUCTIONS[i].p[0]+'" class="main-link construction">'+CONSTRUCTIONS[i].c[1]+'</a><a href="'+LOCALE+'/constructions/'+CONSTRUCTIONS[i].p[0]+'" target="_blank" class="no-decor"><div class="sprite-external-small">&nbsp;</div></a>';
      }else{
        t_html += '<a href="'+LOCALE+'/constructions/'+CONSTRUCTIONS[i].p[0]+'" class="main-link construction">'+PURPOSES[CONSTRUCTIONS[i].p[7]]+'</a><a href="'+LOCALE+'/constructions/'+CONSTRUCTIONS[i].p[0]+'" target="_blank" class="nodecor"><div class="sprite-external-small">&nbsp;</div></a>';
        //t_html += '<b style="font-size: 1.3em; line-height: 1.2em;">'+PURPOSES[CONSTRUCTIONS[i].p[7]]+'</b>';
      }
      t_html += '</div>';
      // 4.2
      t_html += '<div class="text-block gray-6">'+CONSTRUCTIONS[i].p[4]+'</div></td>';
      // 5
      t_html += '<td>';
      if(CONSTRUCTIONS[i].c){
        t_html += '<div>'+CONSTRUCTIONS[i].c[2]+'</div><div class="gray-9">'+_LOCATIONS[CONSTRUCTIONS[i].c[3]]+'</div>';
      }else{
        t_html += '<div class="gray-9">'+_STATES[CONSTRUCTIONS[i].p[8]]+'</div>';
      }      
      if(CONSTRUCTIONS[i].r){
        t_html += '<div class="reminder">'+COLLEAGUES[CONSTRUCTIONS[i].r[0][0]];
        if(CONSTRUCTIONS[i].r[0][2]){ t_html += ', '+CONSTRUCTIONS[i].r[0][2]; }
        t_html += '</div>';
      }
      t_html += '</td></tr>';      
      // save and reset every N rows to avoid stack exhaustion
      if(i % 200 === 0){ $t_search_result = $t_search_result.add($(t_html)); t_html = ''; }
    }
  }
  $t_search_result_filtered = $t_search_result = $t_search_result.add($(t_html));
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("init in " + executionTime + " milliseconds");}catch(e){}
}

function build_companies_dom(){
  var t_html = '';
  var start = new Date().getTime();
  $t_search_result = $();
  if(COMPANIES && COMPANIES.length > 0){
    for (var i = 0; i < COMPANIES.length; ++i) { 
      t_html += '<tr id="'+COMPANIES[i].p[0]+'" class="'+COMPANIES[i].p[1]+'">';
      // 1
      t_html += '<td><div>';
      if(VERBOSE < 3){
        t_html += '<a href="'+LOCALE+'/companies/'+COMPANIES[i].p[0]+'/edit" class="main-link company">'+COMPANIES[i].p[3]+'</a><a href="'+LOCALE+'/companies/'+COMPANIES[i].p[0]+'/edit" target="_blank" class="nodecor"><div class="sprite-external-small">&nbsp;</div></a>';
      }else{
        t_html += '<a href="'+LOCALE+'/companies/'+COMPANIES[i].p[0]+'" class="main-link company">'+COMPANIES[i].p[3]+'</a><a href="'+LOCALE+'/companies/'+COMPANIES[i].p[0]+'" target="_blank" class="nodecor"><div class="sprite-external-small">&nbsp;</div></a>';
      }      
      t_html += '</div><div>'+COMPANIES[i].p[4]+'</div></td>';
      // 2
      t_html += '<td>';
      if(COMPANIES[i].a && COMPANIES[i].a[0][0] == 1){ t_html += '<div class="flask" title="'+COMPANIES[i].a[0][1]+'"></div>'; }
      if(COMPANIES[i].a && COMPANIES[i].a[0][0] > 1 && COMPANIES[i].a[0][0] < 4){ t_html += '<div class="money-coin" title="'+COMPANIES[i].a[0][1]+'"></div>'; }
      if(COMPANIES[i].a && COMPANIES[i].a[0][0] == 3){ t_html += '<div class="newspaper" title="'+COMPANIES[i].a[0][1]+'"></div>'; }
      t_html += '</td>';
      // 3
      t_html += '<td><div><b>'+COMPANIES[i].p[10]+'</b></div><div><a href="mailto:'+COMPANIES[i].p[8]+'" class="gray-6">'+COMPANIES[i].p[8]+'</a></div><div class="gray-9"><a href="'+COMPANIES[i].p[9]+'" class="gray-9">'+COMPANIES[i].p[9]+'</a></div></td>';
      // 4
      t_html += '<td><div>'+COMPANIES[i].p[5]+'</div><div class="gray-9">'+_LOCATIONS[COMPANIES[i].p[6]]+'</div>';
      if(COMPANIES[i].r){
        t_html += '<div class="reminder">'+COLLEAGUES[COMPANIES[i].r[0][0]];
        if(COMPANIES[i].r[0][2]){ t_html += ', '+COMPANIES[i].r[0][2]; }
        t_html += '</div>';
      }
      t_html += '</td></tr>';
      // save and reset every 200 rows, otherwise we get stack exhaustion
      if(i % 200 === 0){ $t_search_result = $t_search_result.add($(t_html)); t_html = ''; }
    }
  }
  $t_search_result_filtered = $t_search_result = $t_search_result.add($(t_html));
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("init in " + executionTime + " milliseconds");}catch(e){}
}

function build_people_dom(){
  var t_html = '';
  var start = new Date().getTime();
  $t_search_result = $();
  if(PEOPLE.length > 0){
    for (var i = 0; i < PEOPLE.length; ++i) { 
      t_html += '<tr id="'+PEOPLE[i].p[0]+'">';
      // 1
      t_html += '<td style="width: 20em">';
      t_html += '<div style="padding-bottom: 0.5em">';
      if(VERBOSE < 3){
        t_html += '<a href="'+LOCALE+'/people/'+PEOPLE[i].p[0]+'/edit" class="main-link person">'+PEOPLE[i].p[1]+'</a><a href="'+LOCALE+'/people/'+PEOPLE[i].p[0]+'/edit" target="_blank" class="no-decor"><div class="sprite-external-small">&nbsp;</div></a>';
      }else{
        t_html += '<a href="'+LOCALE+'/people/'+PEOPLE[i].p[0]+'" class="main-link person">'+PEOPLE[i].p[1]+'</a><a href="'+LOCALE+'/people/'+PEOPLE[i].p[0]+'" target="_blank" class="no-decor"><div class="sprite-external-small">&nbsp;</div></a>';
      }      
      t_html += '</div>';
      t_html += '</td>';
      // 2
      t_html += '<td>';
      if(PEOPLE[i].p[2]){ t_html += '<div style="padding-bottom: 0.5em"><a href="email:'+PEOPLE[i].p[2]+'" style="color: #333">'+PEOPLE[i].p[2]+'</a></div>'; }
      if(PEOPLE[i].p[3]){ t_html += '<div style="color: #999"><a href="skype:'+PEOPLE[i].p[3]+'?chat" style="color: #999">'+PEOPLE[i].p[3]+'</a></div>'; }
      t_html += '</td>';   
      // 3
      t_html += '<td><div class="text-block">'+PEOPLE[i].p[4]+'</div></td>';   
      t_html += '</tr>';
      
      // save and reset every 200 rows, otherwise we get stack exhaustion
      if(i % 200 === 0){ $t_search_result = $t_search_result.add($(t_html)); t_html = ''; }
    }
  }
  $t_search_result_filtered = $t_search_result = $t_search_result.add($(t_html));
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("init in " + executionTime + " milliseconds");}catch(e){}  
}
  
function render_search_result(){
  var start = new Date().getTime();

  // variables and pagination calculations
  var __total_results = $t_search_result_filtered.length;
  var __total_results_absolute = $t_search_result.length;
  var __per_page = 50;
  var __total_pages = Math.ceil(__total_results / __per_page);  
  var __page = 1;
  
  // внешняя зависимость
  if(SEARCH_SETTINGS.page){
    __page = parseInt(SEARCH_SETTINGS.page, 10);
    __page = (isNaN(__page) ? 1 : ((__page > __total_pages) ? __total_pages : __page));
  }
  
  //
  var __start = (__page-1)*__per_page; // start item
  var __end = (__start+__per_page) > __total_results ? __total_results : (__start+__per_page); // end item    
  
  // FIXME: пагинатору тут имхо не место
  var $__right = $('#search-results .search-controls-right'); $__right.html('');
  
  //
  var $paginated_result = (__total_pages > 1) ? $t_search_result_filtered.slice(__start, __end) : $t_search_result_filtered;
  
  //
  // content insertion
  //
  if($paginated_result.length > 0){
    // insert
    $('#search-results > tbody').hide().html($paginated_result).show();
    // highlight
    $('#search-results > tbody').highlight(HIGHLIGHT, true); // FIXME:
    // warnings
    if(__total_results_absolute == 1000 && __total_results == __total_results_absolute){ // TODO: extract global
      $('#search-results > tbody').prepend('<tr><td colspan="5" style="background: #ffc; padding: 0.5em 1em"><img src="images/icons/exclamation.png" /> '+COMMON.threshold_warning+'</td></tr>');
    }
    if(VERBOSE > 3){ // TODO: extract global
      $('#search-results > tbody').prepend('<tr><td colspan="5" style="background: #ffc; padding: 0.5em 1em"><img src="images/icons/exclamation.png" /> '+COMMON.limited_warning+'</td></tr>');
    }
    // back nav.
    if(__page > 2){
      $__right.append('<span style="padding-right: 0.5em"><a href="#" onclick="$.address.parameter(\'page\', 1); return false;" class="shallow">'+COMMON.page_first+'</a></span>');
    }
    if(__page > 1){
      $__right.append('<span style="padding-right: 0.5em"><a href="#" onclick="$.address.parameter(\'page\', '+(__page-1)+'); return false;" class="shallow">'+COMMON.page_previous+'</a></span>');
    }
    // stats.
    var __total_string = '';
    __total_string += '<span style="padding: 0 0.5em">';
    __total_string += '<b>'+(__start+1)+'</b>&ndash;<b>'+__end+'</b> ';
    __total_string += COMMON.page_total_prefix+' ';
    if(__total_results < __total_results_absolute){
      __total_string += '<b><em>'+__total_results+'</em></b>';
    }else{
      __total_string += '<b>'+__total_results+'</b>';
    }
    __total_string += COMMON.page_total_postfix;
    __total_string += '</span>';
    $__right.append(__total_string);
    // forward nav.
    if(__page < __total_pages){    
      $__right.append('<span style="padding-left: 0.5em"><a href="#" onclick="$.address.parameter(\'page\', '+(__page+1)+'); return false;" class="shallow">'+COMMON.page_next+'</a></span>');
    }  
    if(__page < __total_pages-1){
      $__right.append('<span style="padding-left: 0.5em"><a href="#" onclick="$.address.parameter(\'page\', '+(__total_pages)+'); return false;" class="shallow">'+COMMON.page_last+'</a></span>');
    }
  }else{
    // empty 
    $('#search-results > tbody').hide().html('<tr><td colspan="5" style="background: #ffc; padding: 0.5em 1em"><img src="images/icons/exclamation.png" /> '+COMMON.result_empty+'</td></tr>').show();    
  }
  
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("page paginated and inserted in " + executionTime + " milliseconds");}catch(err){}
}

//
// Фильтры
//  
function __render_search_filter_block(selector, prefix, data_object, filter_ids){  
  if(data_object === undefined || $.isEmptyObject(data_object) || (filter_ids !== undefined && filter_ids.length === 0)){
    $(selector).hide(); return;
  }
  
  var t_html = '';
  for(var __key in data_object){
    if(data_object.hasOwnProperty(__key)){
      if(filter_ids !== undefined && $.inArray(parseInt(__key, 10), filter_ids) == -1){ continue; }
      t_html += '<a href="#" id="'+prefix+__key+'"><span><span>'+data_object[__key]+'</span></span></a>';     
    }
  }
  $(selector+' .filter-group-body').html(t_html);
}

function render_construction_search_filters(){
  if(!CONSTRUCTIONS || CONSTRUCTIONS.length === 0){ $('#filters .filter-group').hide(); return false; }
  var start = new Date().getTime();
  //
  try{__render_search_filter_block('#sources', 'sr', SOURCES, SOURCE_IDS); }catch(e){ $('#sources').hide(); }
  try{__render_search_filter_block('#states', 'ls', _STATES); }catch(e){ $('#states').hide(); }
  try{__render_search_filter_block('#reminder-owners', 'ro', COLLEAGUES, REMINDER_OWNER_IDS); }catch(e){ $('#reminder-owners').hide(); }
  try{__render_search_filter_block('#reminder-dates', 'rd', REMINDER_DATES, REMINDER_DATE_IDS); }catch(e){ $('#reminder-dates').hide(); }
  try{__render_search_filter_block('#statuses', 'st', CONSTRUCTION_STATUSES, CONSTRUCTION_STATUS_IDS); }catch(e){$('#statuses').hide(); }
  try{__render_search_filter_block('#stages', 's', STAGES, STAGE_IDS); }catch(e){$('#stages').hide(); }
  try{__render_search_filter_block('#purposes', 'p', PURPOSES, PURPOSE_IDS); }catch(e){$('#purposes').hide(); }
  try{__render_search_filter_block('#roles', 'r', ROLES, ROLE_IDS); }catch(e){$('#roles').hide(); }
  //  
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("filters panel in " + executionTime + " milliseconds");}catch(err){}
}

function render_company_search_filters(){
  if(COMPANIES && COMPANIES.length === 0){ $('#filters .filter-group').hide(); return false; }
  var start = new Date().getTime();
  //
  try{__render_search_filter_block('#states', 'ls', _STATES); }catch(e){ $('#states').hide(); }
  try{__render_search_filter_block('#reminder-owners', 'ro', COLLEAGUES, REMINDER_OWNER_IDS); }catch(e){ $('#reminder-owners').hide(); }
  try{__render_search_filter_block('#reminder-dates', 'rd', REMINDER_DATES, REMINDER_DATE_IDS); }catch(e){ $('#reminder-dates').hide(); }
  try{__render_search_filter_block('#roles', 'r', ROLES, ROLE_IDS); }catch(e){ $('#roles').hide(); }
  //  
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("filters panel in " + executionTime + " milliseconds");}catch(err){}
}

//
// Сортировки
//
function __init_constructions_sort_options(){ 
  if(!CONSTRUCTIONS || CONSTRUCTIONS.length === 0){ return false; }
  
  var $__left = $('#search-results thead .search-controls-left');
  $__left.append('<span style="margin-right: 0.3em"><b>'+COMMON.sort_caption+':</b> </span>');
  
  //
  var t_html = '';
  t_html += '<select class="results-sort" style="width: 12em">';
  t_html += '<option value="1">'+COMMON.by_date+'</option>'; //
  if(CONSTRUCTIONS[0].p[9] !== null){ t_html += '<option value="2" selected="selected">'+COMMON.by_relevance+'</option>'; } //if
  if(CONSTRUCTIONS[0].c){
    t_html += '<option value="3">'+COMMON.by_name+'</option>'; 
    t_html += '<option value="4">'+COMMON.by_address+'</option>';
  }
  t_html += '<option value="7">'+COMMON.by_stage+'</option>'; // stage
  if(CONSTRUCTIONS[0].r){
    t_html += '<option value="5">'+COMMON.by_reminder_owner+'</option>'; //if
    t_html += '<option value="6">'+COMMON.by_reminder_date+'</option>'; //if
  }
  t_html += '</select>';
  $__left.append(t_html);
  
  if(SEARCH_SETTINGS.sort){
    $('#search-results .results-sort').val(SEARCH_SETTINGS.sort);
  }
  
  //
  $('#search-results .results-sort').change(function(){
    $.address.parameter('sort', $(this).val());
  });
}

function sort_construction_results(){
  if(!CONSTRUCTIONS || CONSTRUCTIONS.length === 0){ return false; }
  
  var __sort_type;
  if(SEARCH_SETTINGS.sort){
    __sort_type = parseInt(SEARCH_SETTINGS.sort, 10);
  }else{
    //__sort_type = (CONSTRUCTIONS[0].p[9] !== null) ? 2 : 1;
    __sort_type = 1;
    SEARCH_SETTINGS.sort = __sort_type;
  }
  
  var start = new Date().getTime();
  //
  switch(__sort_type){
  case 1: // date
    CONSTRUCTIONS = CONSTRUCTIONS.sort(function(a,b) { 
      try{ var _a = new Date(a.p[2][0]); var _b = new Date(b.p[2][0]); return -1*((_a>_b)-(_a<_b)); }
      catch(e){ return -1; }
    });
    break;
  case 2: // relevance
    CONSTRUCTIONS = CONSTRUCTIONS.sort(function(a,b) { 
      try{ var _a = new Date(a.p[9]); var _b = new Date(b.p[9]); return -1*((_a>_b)-(_a<_b)); }
      catch(e){ return -1; }
    });
    break;
  case 3: // name
    CONSTRUCTIONS = CONSTRUCTIONS.sort(function(a,b) { 
      try{ var _a = a.c[1]; var _b = b.c[1]; return (_a>_b)-(_a<_b); }
      catch(e){ return -1; }
    });
    break;
  case 4: // address
    CONSTRUCTIONS = CONSTRUCTIONS.sort(function(a,b) { 
      try{ var _a = a.c[2]; var _b = b.c[2]; return (_a>_b)-(_a<_b); }
      catch(e){ return -1; }
    });
    break;
  case 5: // rem. name
    CONSTRUCTIONS = CONSTRUCTIONS.sort(function(a,b) {
      if((a.r === undefined) && (b.r === undefined)){ return 0; }
      else if((a.r === undefined) && (b.r !== undefined)){ return 1; }
      else if((a.r !== undefined) && (b.r === undefined)){ return -1; }
      else{
        var _a = COLLEAGUES[a.r[0][0]];
        var _b = COLLEAGUES[b.r[0][0]];
        return (_a>_b)-(_a<_b);
      }
    });
    break;
  case 6: // rem. date
    CONSTRUCTIONS = CONSTRUCTIONS.sort(function(a,b) {
      if((a.r === undefined) && (b.r === undefined)){ return 0; }
      else if((a.r === undefined) && (b.r !== undefined)){ return 1; }
      else if((a.r !== undefined) && (b.r === undefined)){ return -1; }
      else{
        var _a = new Date(a.r[0][1]);
        var _b = new Date(b.r[0][1]);
        return (_a>_b)-(_a<_b);
      }
    });
    break;
  case 7:
    CONSTRUCTIONS = CONSTRUCTIONS.sort(function(a,b) {
      try{ var _a = STAGES[a.p[6]]; var _b = STAGES[b.p[6]]; return (_a>_b)-(_a<_b); }
      catch(e){ return -1; }
    });
    break;
  default:
    //
  }
  
  $.address.parameter('sort', __sort_type);
  
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("sorted in " + executionTime + " milliseconds");}catch(err){}
}

function __init_companies_sort_options(){ 
  if(!COMPANIES || COMPANIES.length === 0){ return false; }  
  
  var $__left = $('#search-results thead .search-controls-left');
  $__left.append('<span style="margin-right: 0.3em"><b>'+COMMON.sort_caption+':</b> </span>');
  
  //
  var t_html = '';
  t_html += '<select class="results-sort" style="width: 12em">';  
  if(COMPANIES[0].p[11] !== null){ t_html += '<option value="2" selected="selected">'+COMMON.by_relevance+'</option>'; } //if
  t_html += '<option value="3">'+COMMON.by_name+'</option>'; //if  
  t_html += '<option value="4">'+COMMON.by_address+'</option>'; //if
  if(COMPANIES[0].r){
    t_html += '<option value="5">'+COMMON.by_reminder_owner+'</option>'; //if
    t_html += '<option value="6">'+COMMON.by_reminder_date+'</option>'; //if
  }
  t_html += '</select>';
  $__left.append(t_html);
  
  if(SEARCH_SETTINGS.sort){
    $('#search-results .results-sort').val(SEARCH_SETTINGS.sort);
  }
  
  //
  $('#search-results .results-sort').change(function(){
    $.address.parameter('sort', $(this).val());
  });
}

function sort_company_results(){
  if(!COMPANIES || COMPANIES.length === 0){ return false; }
  
  var __sort_type;
  if(SEARCH_SETTINGS.sort){
    __sort_type = parseInt(SEARCH_SETTINGS.sort, 10);
  }else{
    __sort_type = (COMPANIES[0].p[11] !== null) ? 2 : 3;
    SEARCH_SETTINGS.sort = __sort_type;
  }
  
  var start = new Date().getTime();
  //
  switch(__sort_type){
  case 2: // relevance
    COMPANIES = COMPANIES.sort(function(a,b) { 
      try{ var _a = new Date(a.p[11]); var _b = new Date(b.p[11]); return -1*((_a>_b)-(_a<_b)); }
      catch(e){ return -1; }
    });
    break;
  case 3: // name
    COMPANIES = COMPANIES.sort(function(a,b) { 
      try{ var _a = a.p[3]; var _b = b.p[3]; return (_a>_b)-(_a<_b); }
      catch(e){ return -1; }
    });
    break;
  case 4: // address
    COMPANIES = COMPANIES.sort(function(a,b) { 
      try{ var _a = a.p[5]; var _b = b.p[5]; return (_a>_b)-(_a<_b); }
      catch(e){ return -1; }
    });
    break;
  case 5: // rem. name
    COMPANIES = COMPANIES.sort(function(a,b) {
      if((a.r === undefined) && (b.r === undefined)){ return 0; }
      else if((a.r === undefined) && (b.r !== undefined)){ return 1; }
      else if((a.r !== undefined) && (b.r === undefined)){ return -1; }
      else{
        var _a = COLLEAGUES[a.r[0][0]];
        var _b = COLLEAGUES[b.r[0][0]];
        return (_a>_b)-(_a<_b);
      }
    });
    break;
  case 6: // rem. date
    COMPANIES = COMPANIES.sort(function(a,b) {
      if((a.r === undefined) && (b.r === undefined)){ return 0; }
      else if((a.r === undefined) && (b.r !== undefined)){ return 1; }
      else if((a.r !== undefined) && (b.r === undefined)){ return -1; }
      else{
        var _a = new Date(a.r[0][1]);
        var _b = new Date(b.r[0][1]);
        return (_a>_b)-(_a<_b);
      }
    });
    break;
  default:
    //
  }
  
  $.address.parameter('sort', __sort_type);
  
  var stop = new Date().getTime();
  var executionTime = stop - start;
  try{console.log("sorted in " + executionTime + " milliseconds");}catch(err){}
}

function init_constructions_search(){
  // poll settings
  SEARCH_SETTINGS.sort = $.address.parameter('sort');
  SEARCH_SETTINGS.filters = $.address.parameter('filters');
  SEARCH_SETTINGS.select  = $.address.parameter('select');
  SEARCH_SETTINGS.page = $.address.parameter('page');
  
  //
  sort_construction_results();
  build_constructions_dom();
  render_construction_search_filters();
  compute_filtered_result();
  __init_filter_event_delegation();
  __init_result_event_delegation();  
  __init_constructions_print_button();
  __init_constructions_sort_options();
   __select_rows();
  
  $.address.change(function(e){
    // this approach is valid, because only one parameter changes at a time
    if($.address.parameter('sort') != SEARCH_SETTINGS.sort){ // sort
      SEARCH_SETTINGS.sort = $.address.parameter('sort');
      sort_construction_results();
      build_constructions_dom();
      compute_filtered_result();
    }    
    if($.address.parameter('filters') != SEARCH_SETTINGS.filters){ // filters
      SEARCH_SETTINGS.filters = $.address.parameter('filters');
      SEARCH_SETTINGS.page = 1; $.address.parameter('page', 1); // FIXME: 
      compute_filtered_result();
    }
    if($.address.parameter('select') != SEARCH_SETTINGS.select){
      SEARCH_SETTINGS.select = $.address.parameter('select');
      __select_rows();
    }    
    if($.address.parameter('page') != SEARCH_SETTINGS.page){
      SEARCH_SETTINGS.page = $.address.parameter('page');
    }
    //
    render_search_result();
  });
}

function init_companies_search(){
  // poll settings
  SEARCH_SETTINGS.sort = $.address.parameter('sort');
  SEARCH_SETTINGS.filters = $.address.parameter('filters');
  //var SEARCH_SETTINGS.select  = $.address.parameter('select');
  SEARCH_SETTINGS.page = $.address.parameter('page');
  
  //
  sort_company_results();
  build_companies_dom();
  render_company_search_filters();
  compute_filtered_result();
  __init_filter_event_delegation();
  __init_result_event_delegation();
  __init_companies_sort_options();
  
  
  $.address.change(function(e){
    // this approach is valid, because only one parameter changes at a time
    if($.address.parameter('sort') != SEARCH_SETTINGS.sort){ // sort
      SEARCH_SETTINGS.sort = $.address.parameter('sort');
      sort_company_results();
      build_companies_dom();
      compute_filtered_result();
    }   
    if($.address.parameter('filters') != SEARCH_SETTINGS.filters){ // filters
      SEARCH_SETTINGS.filters = $.address.parameter('filters');
      SEARCH_SETTINGS.page = 1; $.address.parameter('page', 1); // FIXME: 
      compute_filtered_result();
    }    
    if($.address.parameter('page') != SEARCH_SETTINGS.page){
      SEARCH_SETTINGS.page = $.address.parameter('page');
    }
    //
    render_search_result();
  });
  
}

function init_people_search(){
  // poll settings
  //SEARCH_SETTINGS.sort = $.address.parameter('sort');
  //SEARCH_SETTINGS.filters = $.address.parameter('filters');
  //var SEARCH_SETTINGS.select  = $.address.parameter('select');
  SEARCH_SETTINGS.page = $.address.parameter('page');
  
  //
  build_people_dom();  
  render_search_result();
  
  $.address.change(function(e){
    if($.address.parameter('page') != SEARCH_SETTINGS.page){
      SEARCH_SETTINGS.page = $.address.parameter('page');
    }
    //
    render_search_result();
  });
}