var init = function() {
    //$("#loading").append("Loading data...");
    // if (window.localStorage && window.localStorage.version == 1) {
    //     window.dictionary = window.localStorage.sowpods;
    //     window.sorted = sort_words(window.dictionary);
    // }


    $.history.init(hash_changed);
    set_callbacks();
    if (!window.loading) {
	load_dictionary();
    }
    // load_dictionary("sowpods", function() {
    // 	    set_callbacks();
    // 	    // Initialise the history after loading the dictionary, so that
    // 	    // searching doesn't happen until afterwards
    // 	    $.history.init(hash_changed);
    // 	});
};

var set_callbacks = function() {
    $("#sowpods").change(update_results);
    $("#twl").change(update_results);
    $("#super").change(update_results);
    $("#order").change(update_results);
};

// var remove_callbacks = function() {
//     $("#sowpods").unbind();
//     $("#twl").unbind();
//     $("#super").unbind();
//     $("#order").unbind();
// };

var hash_changed = function(hash) {
    current_vals = get_vals();
    vals = parse_hash(hash, current_vals);
    apply_values(vals);
    window.vals = vals;
    // Only load the dictionary if there's a query
    if (vals.query.length > 0) {
	load_dictionary();
    }
};

var load_dictionary = function() {
    dictname = window.vals.dict;
    if (dictname != "sowpods" && dictname != "twl") {
	return;
    }
    if (window[dictname + "_dict"]) {
	window.dictionary = window[dictname + "_dict"];
	window.sorted = window[dictname + "_sorted"];
	search();
	return;
    }
    $("#results").html("<h1>Loading dictionary...</h1>");
    window.loading = true;
    $.get("/data/" + dictname + ".dat", success = function(data) {
	    window[dictname + "_dict"] = window.dictionary = data;
	    window[dictname + "_sorted"] = window.sorted = sort_words(window.dictionary);
	    $("#input").focus();
	    window.loading = false;
	    // if (window.localStorage) {
	    //     window.localStorage.sowpods = data;
	    //     window.localStorage.version = 1;
	    // }
	    search();
	});
};

var sort_words = function(words) {
    data_split = window.dictionary.split("\n");
    //data_split = words;
    sorted = [];
    for (i=0; i<data_split.length; ++i) {
	word = data_split[i];
	letters = word.split("");
	s = letters.sort().join("");
	sorted.push(s);
    }
    return sorted.join("\n");
};

var parse_hash = function(hash, default_vals) {
    result = default_vals;
    bits = hash.split("&");
    for (var i=0; i<bits.length; ++i) {
	vals = bits[i].split("=");
	result[vals[0]] = vals[1];
    }
    return result;
};

var make_hash = function(vals) {
    result = [];
    for (var k in vals) {
	result.push(k + "=" + vals[k]);
    }
    return result.join("&");
};

var toggle = function(name, vals) {
    var s = $("#" + name);
    var s_on = s[0].checked ? "on" : "off";
    var sup = vals[name];
    if ((sup == "on" || sup == "off") && sup != s_on) {
	s.click();
    }
}

var apply_values = function(vals) {
    // Super search and order
    toggle("super", vals);
    toggle("order", vals);

    // Dictionary
    var d = vals["dict"];
    if (d == "sowpods" || d == "twl") {
	$("#" + d).click();
    }

    // Input
    if (vals.query) {
	$("#input").val(vals.query);
    }
};

var scores  = [1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10];
var numbers = [9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1];

var score = function(word) {
    var letters = {};
    var A = 'A'.charCodeAt(0);
    for (var i=0; i<word.length; ++i) {
	var l = word.charAt(i);
	if (letters[l]) {
	    letters[l] += 1;
	} else {
	    letters[l] = 1;
	}
    }
    var score = 0;
    for (l in letters) {
	index = l.charCodeAt(0) - A;
	score += scores[index]*Math.min(letters[l],numbers[index]);
    }
    return score;
};

var sort_by_score = function(words) {
    return words.sort(function(a,b) {
	    return score(b) - score(a);
	});
};

var regex_simple = function(query) {
    var re = RegExp("\\b" + query.toUpperCase() + "\\b", "g");
    return re;
};

var regex_substr = function(query) {
    var re = RegExp("\\b.*" + query.toUpperCase() + ".*\\b" ,"g");
    return re;
};

var regex_super = function(query) {
    restring = query.toUpperCase().split("").sort().join("?") + "?";
    var re = RegExp("^" + restring + "$" ,"gm");
    return re;
};

var sanitise = function(query) {
    result = [];
    letters = query.toUpperCase().split("");
    for (var i=0; i<letters.length; ++i) {
	if (letters[i] >= "A" &&
	    letters[i] <= "Z") {
	    result.push(letters[i]);
	}
    }
    return result.join("");
};

var get_results = function(re, dict) {
    var matches = [];
    while ((m = re.exec(dict)) && matches.length < 100000) {
	matches.push(m);
    }
    var results = [];
    for (var i=0; i<matches.length; ++i) {
	m = matches[i];
	results.push(window.dictionary.substr(m.index, m[0].length));
    }
    if (window.vals.order == "on") {
	results = sort_by_score(results);
    }
    return results;
};

var search = function() {
    if (window.loading) {
	return;
    }
    query = window.vals.query ? sanitise(window.vals.query) : "";
    var re;
    var dict;
    if (query.length > 0) {
	var sup = window.vals["super"] == "on";
	var re_func =  sup ? regex_super : regex_simple;
	dict = sup ? window.sorted : window.dictionary;
	re = re_func(query);
	console.log(re);
    } else {
	$("#results").hide();
	return;
    }

    var results = get_results(re, dict);
    // var ms = matches.slice(0,10);
    // var rs = results.slice(0,10);
    // console.log(ms);
    // console.log(rs);
    $("#results").html("");
    $("#results").append("<h1>" + results.length.toString() + " results for " + query + "</h1>");
    $("#results").append("<pre>" + make_columns(results) + "</pre>");
    $("#results").show();
    // for (var i=0; i<matches.length && i<1000; ++i) {
    // 	$("#results").append(matches[i] + "<br>");
    // }
};

var time;
var handle_input = function() {
    if (time) { 
	clearTimeout(time);
    }
    time = setTimeout(update_results, 200);
};

var get_vals = function() {
    vals = {};
    vals["super"] = $("#super")[0].checked ? "on" : "off";
    vals["order"] = $("#order")[0].checked ? "on" : "off";
    vals["dict"] = $("#twl")[0].checked ? "twl" : "sowpods";
    vals["query"] = $("#input").val();
    return vals;
}

var update_results = function() {
    vals = get_vals();
    window.location.hash = make_hash(vals);
};

var make_columns = function(l) {
    // l is a list of words
    // The maximum number of characters in a group:
    max_width = 90;
    max_len = 0;
    for (var i = 0; i<l.length; ++i) {
	max_len = Math.max(max_len, l[i].length);
    }
    spacing = max_len + 3
    columns = Math.floor(max_width/spacing)
    rows = Math.ceil(l.length/columns)
    ret = []
    br = l.length % columns
    if (br == 0) {
        br = columns;
    }
    for (var i=0; i < rows; ++i) {
        var s = "";
        for (var j=0; j < columns; ++j) {
            var num_rows = rows;
	    var ind;
	    if (j >= br) {
                if (i == rows - 1) {
                    continue;
		}
                ind = i + br*rows + (j-br)*(rows - 1);
            } else {
                ind = i + j*rows;
	    }
            if (ind >= l.length) {
		continue;
	    }
	    try {
		var w = l[ind];
		//wp = make_link(w) + ' '*(spacing - len(w))
		var white = "                                         ";
		wp = w + white.substr(0,spacing - w.length);
		s += wp;
	    } catch(e) {
		console.log("Error", e);
		console.log(ind, l.length);
	    }
		    
	}
	ret = ret.concat(s);
    }
    return ret.join("\n");
}
