(function($) {
  
  if(typeof TRYA === 'undefined') {
    TRYA = {};
  }

  function doGetCaretPosition(oField) {
  var iCaretPos = 0;
    // IE Support
    if (document.selection) {
      oField.focus ();
      var oSel = document.selection.createRange ();
      oSel.moveStart ('character', -oField.value.length);
      iCaretPos = oSel.text.length;
    }
    // Firefox support
    else if (oField.selectionStart || oField.selectionStart == '0')
      iCaretPos = oField.selectionStart;
    return (iCaretPos);
  }

  TRYA.search = {
    mouseOverFilter: false,
    queryFocused: false,
    lastLookupNumber: 0,
    lastLookup: null,
    hintLinkEnabled: false,
    
    init: function(queryFieldName, searchMode, data, columnCount) {
      TRYA.search.query = $(queryFieldName);
      TRYA.search.model.searchMode = searchMode;
      TRYA.search.model.colCount = (columnCount != null) ? columnCount : 5;
      TRYA.search.model.saveOriginalCategories(data);
      TRYA.search.model.loadData(data);
      TRYA.search.view.renderTable();
      TRYA.search.view.renderResolvedCategories();
      TRYA.search.view.switchToMode();
      TRYA.search.view.showSearchHint();
      if (!TRYA.search.queryEmpty()) {
        TRYA.search.model.lastAutocomplete = TRYA.search.view.lastLookup = TRYA.search.query.val();
      }
      else {
        TRYA.search.model.lastAutocomplete = TRYA.search.view.lastLookup = "";
      }
      TRYA.search.query
      .keydown(function(event){
          if (event.keyCode == 37 && TRYA.search.model.itemSelected()) { // User pressed left arrow.
              TRYA.search.model.moveSelectedItem(0, -1);
              TRYA.search.view.renderSelectedItem();
              event.preventDefault();
          }
          else if (event.keyCode == 38 && TRYA.search.model.itemSelected()) { // User pressed up arrow.
              TRYA.search.model.moveSelectedItem(-1, 0);
              TRYA.search.view.renderSelectedItem();
              event.preventDefault();
          }
          else if (event.keyCode == 39 && // User pressed right arrow.
            (TRYA.search.model.itemSelected() || 
              (doGetCaretPosition(event.target) == $(this).val().length))) {
                TRYA.search.model.moveSelectedItem(0, 1);
                TRYA.search.view.renderSelectedItem();
                event.preventDefault();
          }
          else if (event.keyCode == 40 &&
            (TRYA.search.model.itemSelected() || 
              (doGetCaretPosition(event.target) == $(this).val().length))) { // User pressed down arrow.            
                TRYA.search.model.moveSelectedItem(1, 0);
                TRYA.search.view.renderSelectedItem();
                event.preventDefault();
          }
          else if (event.keyCode == 27 && TRYA.search.model.itemSelected()) { // User pressed escape key.
              TRYA.search.model.selectItem(-1, 0);
              TRYA.search.view.renderSelectedItem();
          }
          else if ((event.keyCode == 13 || event.keyCode == 32) && TRYA.search.model.itemSelected()) { // User pressed Enter key.
            // there should be a submit over here
            TRYA.search.clickedOnCategory(TRYA.search.model.selectedItem().name);
            event.preventDefault();
          }
      })
      .typeWatch( {
          highlight:true,
          wait:300,
          captureLength: -1,
          callback:TRYA.search.category_autocomplete
      })
      .typeWatch( {
          highlight: false,
          wait: 0,
          captureLength: -1,
          callback:TRYA.search.incrementLookupNumber          
      });
      TRYA.search.tagging.init();
      
      TRYA.search.query.focus(function() {
        if (!TRYA.search.queryFocused) {
          TRYA.search.queryFocused = true;
          if (TRYA.search.hintLinkEnabled || !TRYA.search.queryEmpty()) {
            TRYA.search.changed();
          } else {
            if (TRYA.search.queryEmpty()) {
              TRYA.search.view.showSearchHint();
            }
          }
          if (!TRYA.search.model.searchMode) {
            if (TRYA.search.model.resolvedCategories.length == 0
              && TRYA.search.model.unresolvedCategories.length == 0) {
                TRYA.search.tagging.generateJobCategoriesCall();
            }
          }
          TRYA.search.hintLinkEnabled = false;
        }
      });
      TRYA.search.query.blur(function() {
        TRYA.search.queryFocused = false;
        if(!TRYA.search.mouseOverFilter) {
          TRYA.search.view.hideAutocomplete();
        }
      });
            
      TRYA.search.registerMouseOverFilter('#filter_wrapper');
      TRYA.search.registerMouseOverFilter('.category_names_wrapper #autocomplete_drop');
      
      $(".search_hint_link").click(function(event) {
        TRYA.search.hintLinkEnabled = true;
        if (TRYA.search.queryEmpty()) {
          TRYA.search.view.renderTable(true);
          TRYA.search.category_autocomplete();
        }
        jQuery("#q").focus();
        event.preventDefault();
      });
      
      if ($(queryFieldName + ":focus").length > 0) {
        TRYA.search.query.focus();
      }
      
    },
    queryEmpty: function() {
      return this.query.val() == ""
    },
    messages: function(data) {
      var me = arguments.callee;
      for(i in data){
        me[i] = data[i];
      }
    },
    registerMouseOverFilter: function(selector) {
      $(selector).mouseover(function() {
        TRYA.search.mouseOverFilter = true;
      }).mouseout(function() {
        TRYA.search.mouseOverFilter = false;
        if (!TRYA.search.queryFocused) {
          TRYA.search.view.hideAutocomplete();
        }
      });
      $('#.clear_button a').click(function() {
        TRYA.search.query.val("").keyup().focus();
      });
    },
    category_autocomplete: function(txt) {
      function processResult(result) {
        TRYA.search.model.unselect();
        TRYA.search.view.renderSelectedItem();
        TRYA.search.model.loadData(result);
        // don't continue if query is not focused anymore
        // if (!TRYA.search.queryFocused) {
        //   return;
        // }
        TRYA.search.view.renderTable();
        if (TRYA.search.model.searchMode) {
          TRYA.search.view.switchToMode();
          TRYA.search.view.renderResolvedCategories();
        }
        TRYA.search.view.renderQuery(false, true);
        if (TRYA.search.queryFocused) {
          TRYA.search.changed();
        }
        if (TRYA.search.queryEmpty()) {
          TRYA.search.view.hideAutocomplete();
        }
      }
      function cache(key){
        var cached = TRYA.search.category_autocomplete.cache
        if(cached != null){
          return cached[key];
        }
        return null;
      }
      function addCache(key, data){
        var cached = TRYA.search.category_autocomplete.cache
        if(cached == null){
          cached = {};
          TRYA.search.category_autocomplete.cache = cached;
        }
        cached[key] = data;
      }
            
      var queryValue = TRYA.search.query.val();
      if (TRYA.search.model.lastAutocomplete != queryValue) {
        TRYA.search.model.lastAutocomplete = queryValue;
	      var dataArray;
        if (TRYA.search.model.searchMode) {
          dataArray = { search: TRYA.search.query.val() };
        } else {
          dataArray = { search: TRYA.search.query.val(), last: 1 };
        }
        var result = cache(queryValue)
        if(result != null){
          processResult(result);
          return false;
        }
      
        TRYA.search.incrementLookupNumber(TRYA.search.query.val());
        var thisLookupNumber = TRYA.search.lastLookupNumber;
      
        $.ajax(
        {
          // TODO tady se musi zavolat /categories a vysledek se znovuinitializuje do 'category_table'
            type: "GET",
            url: "/categories.js",
            data: dataArray,
            dataType: "json",
            beforeSend: TRYA.search.view.showLoadingIcon,
            success: function(result) {
              if (TRYA.search.lastLookupNumber == thisLookupNumber) {
                addCache(queryValue, result)
                TRYA.search.view.hideLoadingIcon();
                processResult(result);
              }
            },
            error: function() {
              TRYA.search.view.hideLoadingIcon();
            }
        });
      }
      return false;
    },
    clickedOnCategory: function(category) {
      TRYA.search.model.unselect();
      TRYA.search.view.renderSelectedItem();
      TRYA.search.model.setCategory(category);
      TRYA.search.view.renderQuery(true);
      TRYA.search.query.focus();
    },

    incrementLookupNumber: function(event) {
      if (TRYA.search.lastLookup != event) {
        TRYA.search.lastLookupNumber = TRYA.search.lastLookupNumber + 1;
        TRYA.search.lastLookup = event;
      }
    },

    changed: function(){
      if(TRYA.search.model.searchMode || TRYA.search.model.searchedToken.length > 0){
        TRYA.search.view.showAutocomplete();
      }
    },

    hookCategoryClickHandler: function() {
      $("a.category_cell").click(function(event) {
        if (TRYA.search.model.searchMode) {
          TRYA.search.view.lockLoadingIcon = true;
        }
        TRYA.search.clickedOnCategory($(this).attr("pure_name"));
        if (TRYA.search.model.searchMode) {
          TRYA.search.view.showLoadingIcon();
          $("#search_form form:first").submit();
        }
        
        event.preventDefault();
        return false;
      });
    },
    model: {
      selectedRow: -1,
      selectedColumn: 0,
      rowCount: 0,
      itemCount: 0,
      table: null,
      searchedToken: null,
      path: null,
      state: null,
      query: null,
      resolvedCategories: null,
      originalCategories: [],
      lastAutocomplete: "-1",
      notDisplayed: 0,
      totalCategories: 0,
      categoriesRendered: false,
    
      loadData: function(data) {
        var sliceSize = TRYA.search.model.searchMode ? 15 : 12;
        this.totalCategories = data['filtered_categories'].length;
        sliced = data['filtered_categories'].slice(0,sliceSize);
        this.notDisplayed = (data['filtered_categories'].size() - sliced.size());
        data['filtered_categories'] = sliced;

        TRYA.search.model.resolvedCategories = [];
        TRYA.search.model.unresolvedCategories = [];
        TRYA.search.model.searchedToken = data['searched_token'];
        TRYA.search.model.path = data['search_path'];
        for(var i=0; i<data['search_text_categories'].length; i++) {
          TRYA.search.model.setCategory(data['search_text_categories'][i].category.name);
        }
        for(i=0; i<data['search_text_non_categories'].length; i++) {
          TRYA.search.model.unresolvedCategories.push(data['search_text_non_categories'][i]);
        }
        TRYA.search.model.createTable(data['filtered_categories']);
      },
      saveOriginalCategories: function(data) {
        for(var i=0; i<data['search_text_categories'].length; i++) {
          TRYA.search.model.originalCategories.push(data['search_text_categories'][i].category.name);
        }
      },
      createTable: function(data) {
        var rows = [], col = 0, row = 0;
      
        TRYA.search.model.itemCount = data.length;
        TRYA.search.model.rowCount = Math.ceil(TRYA.search.model.itemCount / TRYA.search.model.colCount);
    
        var offset = 0;
        for(var i=0; i < TRYA.search.model.itemCount; i++) {
          while(true) {
            col = Math.floor((i+offset) / TRYA.search.model.rowCount);
            row = (i+offset) % TRYA.search.model.rowCount;
            if (TRYA.search.model.isCellBlank(row, col)) {
              offset++;
            } else {
              break;
            }
            if (offset > 100) {
              break;
            }
          }
          if(rows[row] == null) {
            rows[row] = [];
          }
          rows[row][col] = data[i]['category'];
        }
        TRYA.search.model.table = rows;
      },
      isCellBlank: function(row, column) {
        var result = (
          row + 1 > TRYA.search.model.rowCount ||
          row < 0 ||
          column + 1 > TRYA.search.model.colCount || 
          column < 0 ||
          row * TRYA.search.model.colCount + column + 1 > TRYA.search.model.itemCount
        );
        // console.log("isCellBlank="+result+", row="+row+", column="+column+", rowCount="+TRYA.search.model.rowCount+", colCount="+TRYA.search.model.colCount+", "+TRYA.search.model.itemCount+" - "+(row * TRYA.search.model.colCount + column)+" < "+TRYA.search.model.blankCells+"")
        return result;
      },
      selectItem: function(row, column) {
        TRYA.search.model.selectedRow = row;
        TRYA.search.model.selectedColumn = column;
      },
      selectedItem: function() {
        return TRYA.search.model.table[TRYA.search.model.selectedRow][TRYA.search.model.selectedColumn];
      },
      unselect: function() {
        TRYA.search.model.selectItem(-1, 0);
      },
      // The main features is that move down wraps around to next column (or previous for move up)
      // It also takes into account that the td cells can be irregular (some row incomplete)
      moveSelectedItem: function(rowInc, columnInc) {
        row = TRYA.search.model.selectedRow;
        column = TRYA.search.model.selectedColumn;
        rowCount = TRYA.search.model.rowCount;

        // translate right arrow move to down if no selection exists
        if(row == -1 && columnInc == 1 && rowInc == 0){
          row = 0;
          columnInc = 0;
        }
        if(rowInc != 0){ // either cell exists or let it slide up
          if(!TRYA.search.model.isCellBlank(row+rowInc, column) || (column == 0 && row + rowInc < 0)) {
            row = row+rowInc;
          }
          else {
            if(rowInc > 0)
              rowCandidate = 0; // going down => start from next column down
            else
              rowCandidate = rowCount-1; // going up => start from previous column up
    
            columnAdjustment = rowInc;
            // if the pass through the next or previous column not successfull, it stays
            while(rowCandidate < rowCount && rowCandidate >= 0) {
              if(!TRYA.search.model.isCellBlank(rowCandidate, column+columnAdjustment)){
                // row found
                row = rowCandidate;
                column = column+columnAdjustment
                break;
              }
              rowCandidate = rowCandidate+rowInc;
            }
          }
        }
        if(columnInc != 0){
          if(!TRYA.search.model.isCellBlank(row, column+columnInc))
            column = column+columnInc;
          else {
            if(column + columnInc < 0){
                row = -1;
                column = 0;
            }
          }
        }
        TRYA.search.model.selectItem(row, column);
      },
      // TODO simplify
      itemSelected: function() {
          return(TRYA.search.model.selectedRow != -1)
      },
      setCategory: function(cat) {
        TRYA.search.model.resolvedCategories.push(cat);
        // console.log("resolvedCategories: "+TRYA.search.model.resolvedCategories);
      },
      unresolvedCategoriesWithoutToken: function() {
        var result = TRYA.search.model.unresolvedCategories.clone();
        if (result.last() == TRYA.search.model.searchedToken) {
          result.pop();
        }
        // console.log("unresolvedCategoriesWithoutToken="+TRYA.search.model.unresolvedCategories);
        // console.log("token="+TRYA.search.model.searchedToken);
        // console.log("result="+result);
        return result;
      },
      hasRelatedCategories: function() {
        return (TRYA.search.model.searchMode &&
          TRYA.search.model.itemCount > 0);
      },
      queryOriginal: function() {
        if (TRYA.search.model.originalCategories.length != TRYA.search.model.resolvedCategories.length)
          return false;
        var result = true;
        for(var i=0; i<TRYA.search.model.originalCategories.length; i++) {
          if (TRYA.search.model.originalCategories[i] != TRYA.search.model.resolvedCategories[i]) {
            result = false;
            break;
          }
        }
        return result;
      }
    },
    view: {
      buttonFlashed: false,
      lockLoadingIcon: false,
            
      renderTable: function(force) {
        if (force || !TRYA.search.queryEmpty()) {
          var rows = TRYA.search.model.table;
          $("table.category_table").html("");
          var td;
          var tr;
          for(var i=0; i < rows.length; i++) {
            tr = $(document.createElement('tr'));
            for(var j=0; j < rows[i].length; j++) {
              td = $(document.createElement('td')).append(TRYA.search.view.renderCategoryCell(rows[i][j]));
              tr.append(td);
            }
            $("table.category_table").append(tr);
          }
          TRYA.search.model.categoriesRendered = true;
          TRYA.search.hookCategoryClickHandler();
          TRYA.search.view.renderMessage();
        } else {
          $("table.category_table").html("");
          TRYA.search.model.categoriesRendered = false;
        }
        this.showNotDisplayed();
      },

      renderMessage: function(){
        var unres = TRYA.search.model.table.length == 0 ?
          TRYA.search.model.unresolvedCategories : TRYA.search.model.unresolvedCategoriesWithoutToken();
        if(unres.size() != 0 && unres[0]){
          var span_high = '<span class="orange bold">';
          var msg = TRYA.search.messages.creating +
            (unres.size() > 1 ? span_high+unres.size()+'</span> '+TRYA.search.messages.new_categories :
            TRYA.search.messages.new_category);
          var cats = span_high + unres.join(", ") + '</span>';
          $('#category_message').html(msg + cats +
            ((unres.size() > 1) ? TRYA.search.messages.tip_use_existing : TRYA.search.messages.tip_comma));
        }else{
          $('#category_message').html("");
        }
      },
      createTag: function(name, hiName, innerElement, noLink) {
        if(typeof noLink === 'undefined'){
          noLink=false;
        }
        if (hiName == null)
          hiName = name;
        var tag = $(document.createElement('div'))
          .addClass('tag');
        var tagLeft = $(document.createElement('span')).addClass('tag_left');
        var tagCenter = $(document.createElement('span')).addClass('tag_center');
        var tagRight = $(document.createElement('span')).addClass('tag_right');
        var link;
        if(noLink){
          link = $("<p></p>").append(tagLeft).append(tagCenter).append(tagRight).children();
        }else{
          link = $(document.createElement('a'))
            .attr('href', TRYA.search.model.path)
            .attr('pure_name', name)
            .attr('title', name && name.length > TRYA.search.view.maxCategoryVisibleLen() ? name : "")
            .addClass('category_cell')
            .append(tagLeft)
            .append(tagCenter)
            .append(tagRight);
        }
        tag.append(link);
        if (innerElement != null)
          tagCenter.append(innerElement);
        tagCenter.append(hiName);
        return tag
      },
      renderCategoryCell: function(category) {
        if (category === null) {
          return "";
        }
        var categoryName = category['name'] != null ? category['name'] : "N/A";
        var count = $(document.createElement('span'))
          .addClass('c_what')
          .append(category['cnt']);
        var tag = TRYA.search.view.createTag(categoryName, TRYA.search.view.highlightedName(category), count);
        var wrapper = $(document.createElement('span'))
          .append(tag);
        return wrapper;
      },
      renderSelectedItem: function() {
        $('#category_list td.cat_selected').removeClass('cat_selected');
        $('#category_list tr:nth-child('+(TRYA.search.model.selectedRow+1)+') td:nth-child('+(TRYA.search.model.selectedColumn+1)+')').addClass('cat_selected');
      },
      renderQuery: function(withoutToken, onlyChanged) {
        withoutToken = withoutToken || false;
        onlyChanged = onlyChanged || false;
        var count = TRYA.search.model.resolvedCategories.size();
        if(onlyChanged){          
          if(arguments.callee.resolvedCount == count){
            // console.log('skip ');
            return;
          }
          else{
            arguments.callee.resolvedCount = TRYA.search.model.resolvedCategories.size();
            // console.log('storing ' + (arguments.callee.resolvedCount));
          }
        }
        var unresolved = withoutToken ? TRYA.search.model.unresolvedCategoriesWithoutToken() : TRYA.search.model.unresolvedCategories;
        // whitespace instead of comma:
        // var trailingComma = (unresolved == null || unresolved.size() === 0) && TRYA.search.model.resolvedCategories.size() === 0 ? "" : " ";
        var trailingComma = (unresolved == null || unresolved.size() === 0) &&
            TRYA.search.model.resolvedCategories.size() > 0 ? ", " : "" ;
        var result = TRYA.search.model.resolvedCategories.concat(unresolved);

        TRYA.search.query.val(result.join(", ") + trailingComma);
        // whitespaces instead of commas: 
        // var quotedResult = this.quoteWordsWithWhitespace(result);
        // TRYA.search.query.val(quotedResult.join(" ") + trailingComma);
      },
      debug: function() {
        console.log("unresolvedCategories: " + TRYA.search.model.unresolvedCategories);
        console.log("resolvedCategories  : " + TRYA.search.model.resolvedCategories);
        console.log("searchedToken       : " + TRYA.search.model.searchedToken);
      },
      quoteWordsWithWhitespace: function(arr) {
        // this will quote words that contain at least one whitespace with " "
        var result = new Array();
        var reWhiteSpace = new RegExp(/\s+/);
        for (var i = 0; i < arr.length; i++) {
          if (reWhiteSpace.test(arr[i])) {
            result[i] = '"' + arr[i] + '"';
          } else {
            result[i] = arr[i];
          }
        }
        return result;
      },
      maxCategoryVisibleLen: function(){
        return 24;
      },
      highlightedName: function(category, maxLen) {
        if(typeof maxLen === 'undefined'){
          maxLen=TRYA.search.view.maxCategoryVisibleLen();
        }
        var cat = category.name
        if(cat.length > maxLen){
            cat = cat.substring(0, maxLen) + '...';
            //console.log(categoryName +'|'+TRYA.search.view.highlightedName(category));
        }
        if (category.h_i !== null) {
          var pos = parseInt(category.h_i.first());
          return cat.substring(0, pos) +
            '<strong class="highlight">' +
            cat.substring(pos, pos + TRYA.search.model.searchedToken.length) +
            '</strong>' +
            cat.substring(pos + TRYA.search.model.searchedToken.length);
        } else {
          return cat;
        }
      },
      showLoadingIcon: function() {
        $(".loader_icon").show();
      },
      hideLoadingIcon: function() {
        if (!TRYA.search.view.lockLoadingIcon) {
          $(".loader_icon").hide();
        }
      },
      switchToMode: function() {
        related = (TRYA.search.model.searchMode &&
          TRYA.search.model.resolvedCategories.length > 0);
        if(related){
          $('#filter').addClass('filter_related').removeClass('filter_regular');
          $('#category_list').addClass('filter_related').removeClass('filter_regular');
        }else{
          $('#filter').addClass('filter_regular').removeClass('filter_related');
          $('#category_list').addClass('filter_regular').removeClass('filter_related');
        }
      },
      showAutocomplete: function() {
        var auto_box = $("#autocomplete_drop");
        if(auto_box.hasClass('f_c_over')){
          $("#filter").addClass("filter_autocomplete");
          auto_box.show();
        }
        TRYA.search.view.hideSearchHint();
      },
      hideAutocomplete: function() {
          var auto_box = $("#autocomplete_drop");
          if(auto_box.hasClass('f_c_over')){
            $("#filter").removeClass("filter_autocomplete");
            auto_box.hide();
          }
          TRYA.search.view.showSearchHint();
      },
      showSearchHint: function() {
        this.hideSearchHint();
        if (TRYA.search.model.hasRelatedCategories()) {
          if (TRYA.search.queryFocused) {
            $("#general_categories_hint").show();
          } else {
            if (TRYA.search.model.resolvedCategories.length > 0) {
              $("#related_categories_hint").show();
            } else {
              $("#most_used_categories_hint").show();
            }
          }
        }
        else {
          $("#general_categories_hint").show();
        }
      },
      hideSearchHint: function() {
        $(".search_hint").hide();
      },
            
      toggleAutocomplete: function() {
        var auto_box_visible = $("#autocomplete_drop:visible");
        if (auto_box_visible.size > 0) {
          TRYA.search.view.hideAutocomplete();
        }
        else {
          TRYA.search.view.showAutocomplete();
        }
      },
      
      showNotDisplayed: function() {
        if (TRYA.search.model.notDisplayed > 0 && TRYA.search.model.categoriesRendered) {
          $("#not_displayed_category_count_hint").html("zobrazeno prvních " + (TRYA.search.model.totalCategories - TRYA.search.model.notDisplayed) + " kategorií.").show();
        } else {
          $("#not_displayed_category_count_hint").html("").hide();
        }
      },
      renderResolvedCategories: function() {
        if (TRYA.search.model.searchMode &&
          TRYA.search.model.resolvedCategories.length > 0) {
          $("#related_categories_label").show();
          var result = [];
          var element = $("#related_categories");
          element.html("");
          var from = TRYA.search.model.resolvedCategories.length - 2;
          if (from > 0) {
            element.append("<div style='margin-top: 5px;float: left'>...</div>");
          } else {
            from = 0;
          }
          for(var i=from; i<TRYA.search.model.resolvedCategories.length; i++) {
            element.append(TRYA.search.view.createTag(
              TRYA.search.model.resolvedCategories[i], null, null, true));
          }
        } else {
          $("#related_categories_label").hide();
        }        
      }
    },
    tagging: {
      generateJobCategoriesCall: function() {
        if (!this.fieldsEmpty()) {
          $.ajax(
          {
            type: "GET",
            url: "/zakazky/parse_description.js",
            beforeSend: TRYA.search.view.showLoadingIcon,
            data: TRYA.search.tagging.gatherData(),
            dataType: "json",
            success: function(data) {
              TRYA.search.view.hideLoadingIcon();
              TRYA.search.model.resolvedCategories = [];
              TRYA.search.model.unresolvedCategories = [];
              for(var i=0; i<data.job_category_names.length; i++) {
                TRYA.search.model.setCategory(data.job_category_names[i]);
              }
              TRYA.search.view.renderQuery();
            },
            error: function() {
              TRYA.search.view.hideLoadingIcon();
            }
          })
        }
      },
      // This is copy-paste, can be improved     
      generateProviderCategoriesCall: function() {
        $.ajax(
        {
          type: "GET",
          url: "/providers/suggest_categories.js",
          beforeSend: TRYA.search.view.showLoadingIcon,
          data: {
            id: $('#hidden_user_id').val(),
            category_names: $('#user_category_names').val()
          },
          dataType: "json",
          success: function(data) {
            TRYA.search.view.hideLoadingIcon();
            TRYA.search.model.resolvedCategories = [];
            TRYA.search.model.unresolvedCategories = [];
            for(var i=0; i<data.job_category_names.length; i++) {
              TRYA.search.model.setCategory(data.job_category_names[i]);
            }
            TRYA.search.view.renderQuery();
          },
          error: function() {
            TRYA.search.view.hideLoadingIcon();
          }
        })
      },
      fieldsEmpty: function() {
        return $('#job_header').size() == 0 
          && $('#job_description').size() == 0 
          && $('#job_demand_header').size() == 0 
          && $('#job_demand_description').size() == 0;
      },
      gatherData: function() {
        var result = { 
          description: $('#job_header').val() + " " + $('#job_description').val() + " " + $('#job_demand_header').val() + " " + $('#job_demand_description').val(),
          category_names: $('#job_category_names').val() 
        }
        return result;
      },
      init: function() {
        $('#category_names_button')
          .click(function(event) {
            TRYA.search.tagging.generateJobCategoriesCall();
            event.preventDefault();
          })
          .mouseover(function() {
            $(".category_names_button_hint").show();
          })
          .mouseout(function() {
            $(".category_names_button_hint").hide();
          });

        $('#provider_category_names_button')
          .click(function(event) {
            TRYA.search.tagging.generateProviderCategoriesCall();
            event.preventDefault();
          })
          .mouseover(function() {
            $(".category_names_button_hint").show();
          })
          .mouseout(function() {
            $(".category_names_button_hint").hide();
          });
      }
    }


  }
})(jQuery);