function search_init(json) {
    SEARCH_DATA = json;
    SEARCH_DATA_CACHE = {};
    SEARCH_NO_DATA = "NO_DATA";
    enable_autocomplete("#search", json.words);
    $.historyInit(search_from_hash);
}

function search_keywords_loaded(json) {
}

function enable_autocomplete(id, data) {
    $(id).autocomplete({"data": data, "multiple": true})
}

function search_do_clear() {
    $("#results").children().remove();
}

// Calculated integer division numerator / denominator
function int_div(numerator, denominator) {
    var remainder = numerator % denominator;
    var quotient = ( numerator - remainder ) / denominator;
    return quotient;
}

function search_store_bucket(bucket_id, bucket) {
    SEARCH_DATA_CACHE[bucket_id] = bucket;
}

function search_get_data(id) {
    var bucket_id = String(int_div(id, SEARCH_DATA.idSplit));
    var bucket = SEARCH_DATA_CACHE[bucket_id];
    if (bucket) {
        return bucket[String(id)];
    } else {
        $.getJSON("tags-" + bucket_id + ".js",
                  function (new_bucket) {
                      search_store_bucket(bucket_id, new_bucket)
                  });
        return SEARCH_NO_DATA;
    }
}

function search_do() {
    $.historyLoad($("#search").attr("value"));
}

function search_from_hash(hash) {
    if (hash) {
        $("#search").attr("value", hash);
        search_from_field();
    } else {
        
    }
}

function search_from_field() {
    if (!SEARCH_DATA) {
        }

    var words = $("#search").attr("value").split(", ");
    var idsets = new Array();
    $.each(words, function(i, word) {
        var idset = SEARCH_DATA.idByWord[word];
        if (idset) {
            idsets.push(idset);
        }
    });
    var matches = set_intersection(idsets);

    search_show_results(matches);
}

function search_show_results(matches) {
    search_do_clear();

    var datas = new Array();
    var no_data = false;
    $.each(matches, function (i, val) {
        data = search_get_data(val);
        if (data === SEARCH_NO_DATA) {
            no_data = true;
        }
        datas.push(data);
    });
    
    if (no_data) {
        $("#results").append($("<p>").attr("class", "fetching").text("Fetching results..."));
        setTimeout(function () {
            search_show_results(matches);
        }, 200);
    } else {
        $.each(datas, function (i, data) {
            var thumbcell = $("<div>").attr("class", "thumbcell");
            $("#results").append(thumbcell);
            var thumbnail = $("<div>").attr("class", "thumbnail")
                thumbcell.append(thumbnail);
            thumbnail.append($("<a>").attr("href", data.page).append($("<img>").attr("class", "picture").attr("src", data.thumb).attr("alt", data.thumb)));
        });
    }
}

/**
 * Compute intersection of sets, given as array or ordered arrays.
 */
function set_intersection(sets) {
    if (sets.length == 1) {
        return sets[0];
    } else if (sets.length > 1) {
        var result = new Array();
        for (i in sets[0]) {
            result.push(sets[0][i]);
        }
        for (var i = 1; i < sets.length; i++) {
            result = intersect(result, sets[i]);
        }
        return result;
    } else {
        return new Array();
    }
}

function intersect(target, source) {
    var result = new Array();
    var ti = 0;
    for (var i = 0; i < source.length; i++) {
        while (target[ti] < source[i] & ti < target.length) {
            ti++;
        }
        if (ti == target.length) {
            break;
        }
        if (source[i] == target[ti]) {
            result.push(source[i]);
        } else if (source[i] < target[ti]) {
            continue;
        }
    }
    return result;
}

function search_reset() {
    $("#search").attr("value", "");
}

$(document).ready(function(){
    $.getJSON("tags.js", search_init);
});


