var lexical_units = [];         // list of all lexical_units
var base;                       // base form of lexical unit
var free_luid = -1;             // these ids will be temporarely given to new lexical units
var free_sense = {};                 // what sense should be given to new lexical unit
var lexical_units_frames = [];
var lexical_units_num = [];
var part_of_speech;

// store lexical units from database
function memorizeLexicalUnits(input_lexical_units) {
    lexical_units = input_lexical_units;
    
    var i;
    for (i = 0; i < lexical_units.length; i++) {
        lexical_unit_examples[lexical_units[i].id] = [];
    }
}

function basicLexicalUnitsData(info){
    base = info.base;
    free_sense = info.sense;
    part_of_speech = info.pos;
}


// create new lexical_unit
function createLexicalUnit(refl, glossa, relation, to) {

    if (((typeof to) == 'undefined') && (relation != 2)) {
        return
    }

    var refl_text = "";
    if (refl == "true") {
        refl_text = " się";
    } else {
        refl_text = "";
    }

    if (typeof(free_sense[base + refl_text]) == 'undefined'){
	free_sense[base + refl_text] = 'A';
    }
    
    var lu = {base: base + refl_text, glossa: "" + glossa, definition: "", id: free_luid, luid: -1, refl: refl, glossa: glossa, pos: part_of_speech, sense: free_sense[base + refl_text], relation: relation, to: to, location: ""};
    var operation = {operation: 'add_unit', unit:lu};
    lexical_units.push(lu);
    lexical_unit_examples[free_luid] = []
    units_operations.push(operation); 
    free_sense[base + refl_text] = String.fromCharCode(free_sense[base + refl_text].charCodeAt(0) + 1);
    free_luid -= 1;
}

// is unit with given luid from PlWN?
function isPlWNUnit(luid) {
    var i = indexOfId(lexical_units, luid);
    if (i >= 0) {
        if (lexical_units[i].luid == -1) {
            return false;
        }
    }
    return true;
}

// remove lexical unit (that is not from PlWN)
function destroyLexicalUnit(luid) {
    var i = indexOfId(lexical_units, luid);
    if (i >= 0) {
        if (lexical_units[i].luid == -1) {
            lexical_units.splice(i, 1);
            
            var j;
            for (j = 0; j < lexical_unit_examples[luid].length; j++) {
                var k = indexOfId(examples, lexical_unit_examples[luid][j]);
                if (k >= 0) {
                    examples[k].meanings = [];
                }
            }
            lexical_unit_examples[luid] = [];
            
            var operation = {operation: 'remove_unit', luid: luid};
            units_operations.push(operation);
        }
    }
}

function getGlossa(luid) {
    var lu = lexical_units[indexOfId(lexical_units, luid)];
    return lu.glossa;
}

// set glossa for unit with given luid
function setGlossa(luid, glossa) {
    var i = indexOfId(lexical_units, luid);
    lexical_units[i].glossa = "" + glossa;
    units_operations.push({operation: 'set_glossa', unit: luid, value: lexical_units[i].glossa});
}

function getLocation(luid) {
    if (isPLWNUnit(luid)){
	var lu = lexical_units[indexOfId(lexical_units, luid)];
	return lu.location;	
    } else {
	return "";
    }
}

// save all changes to meanings (lexical units)
function saveMeanings() {
    $.ajax({
    	type: "POST",
        dataType: "json",
        url: ajax_update_meanings,
        data: {"operations": JSON.stringify(units_operations), 
        	   "lemma_id": lemma_id},
        success: function(data){
            memorizeLexicalUnits(data.lexical_units);
            basicLexicalUnitsData(data.informations);
            updateExamplesConnections();
        },
        async: false
    });

    $.ajax({
        dataType: "json",
        url: ajax_examples,
        data: {"lemma_id": lemma_id},
        success: function(data){
            memorizeExamples(data.examples, true);
        },
        async: false
    });

    $.ajax({
        dataType: "json",
        url: ajax_frames,
        data: {"lemma_id": lemma_id},
        success: function(data){
	    getFrames(data.frames_display);
	    displayFrames();
	    memorizeConnections(data.connections.connected, data.connections.connected_reverse);
	    alternationCounts(data.alternations);
	    $("#semantic-frames-count").empty();
	    $("#semantic-frames-count").append(data.frames_count);
        },
        async: false
    });

    units_operations = [];
}

// get all meanings as radio-button form named "meaning"
function getMeanings() {
    var display = "";
    
    var i;
    for (i = 0; i < lexical_units.length; i++) {
	var hasExamples = hasExample(lexical_units[i].id);
        display += "<input type = \"radio\" name = \"meaning\" value = \"" + lexical_units[i].id + "\">";
	if (hasExamples) {
	    display += "<b>";
	}
	display += lexical_units[i].base + "-" + lexical_units[i].sense;
	if (hasExamples) {
	    display += "</b>";
	}
	display += "<div id=\"glossa_" + lexical_units[i].id + "\">" + " <i>" + lexical_units[i].definition + "</i>";
	if (lexical_units[i].definition != "") {
	    display += "<br>";
	}
	display += lexical_units[i].glossa 
	if (lexical_units[i].glossa != "") {
	    display += "<br>";
	}
	display += lexical_units[i].location + "</div>";
    }
    
    return display;
}

// get all meanings as checkbox-type form, meanings with frame are disabled
function getMeaningsSelection() {
    var display = "";
    
    var i;
    for (i = 0; i < lexical_units.length; i++) {
        display += "<input type = \"checkbox\" name = \"meaning\" value = \"" + lexical_units[i].id + "\""
        var j;
        for (j = 0; j < lexical_units_num.length; j++) {
            if (indexOfId(lexical_units_num[j], lexical_units[i].id) != -1) {
                display += " disabled = \"True\""
            }
        }
        display += ">" + lexical_units[i].base + "-" + lexical_units[i].sense + "<br><div id=\"glossa_" + lexical_units[i].id + "\">" + lexical_units[i].glossa + "</div>"
    }

    return display;
}

// get all meanings as checkbox-type form, meanings with frame are disabled
function getMeaningsSelectionForFrame(frame_id) {
    var display = "";
    var id = "" + frame_id;
    

    // podstawowe znaczenia
    display += "<div>";
    var i;
    for (i = 0; i < lexical_units.length; i++) {
        display += "<input type = \"checkbox\" name = \"meaning\" value = \"" + lexical_units[i].id + "\""
        var j;
        for (j = 0; j < lexical_units_num.length; j++) {
            if 
            (indexOfId(lexical_units_num[j], lexical_units[i].id) != -1) {
                if (lexical_units_frames[j].indexOf(id) != -1) {
                    display += " checked";
                } else {
                    display += " disabled = \"True\"";
                }
            }
        }
        display += ">" + lexical_units[i].base + "-" + lexical_units[i].sense + "<br><div id=\"glossa_" + lexical_units[i].id + "\">" + lexical_units[i].glossa + "</div>"
    }
    display += "</div>";

    // znaczenia wielowyrazowe

    var lexicalisation = [];

    display += "<br/>";

    display += "<div>";

    if (frame_content[frame_id].lemma.include) {
        var rows = getPhraseologicalAlternations(frame_id);
        var lem = frame_content[frame_id].lemma.csv_class;
	var j;
	for (j = 0; j < rows.length; j++) {
	    var options = [];
            var vrb = [];
            var pre = [];
            sid_alt = rows[j].split('_');
	    var sch = "schema_" + sid_alt[0] + "_";
	    var k;
	    if (typeof(schemas_content[sch]) != 'undefined'){
		for (k = 0; k < schemas_content[sch].display.arguments[0].length; k++) {
		    var proper = schemas_content[sch].display.arguments[0][k].csv_id + "alt_" + sid_alt[1] + "_";
                    if (connected[lem].indexOf(proper) != -1) {
			if (schemas_content[sch].display.arguments[0][k].vrb != null &&
                            schemas_content[sch].display.arguments[0][k].vrb.length > 0) {
                            pre = pre.concat(schemas_content[sch].display.arguments[0][k].lex);
                            vrb = schemas_content[sch].display.arguments[0][k].vrb;
			} else {
                            options.push(schemas_content[sch].display.arguments[0][k].lex);
			}
		    } 
		}
	    }
            if (vrb.length == 0) {
		var lex = {lemma: [base], pre: pre, args: options};
		if (hasRefl(sch)) {
                    if (isNeg(sch)) {
                        lex.lemma = ["nie " + base + " się"];
                    } else {
                        lex.lemma = [base + " się"];
                    }
		} else {
                    if (isNeg(sch)) {
                        lex.lemma = ["nie " + base];
                    } else {
                        lex.lemma = [base];
                    }
                }
		lexicalisation.push(lex);
            } else {
		var lex = {lemma: vrb, pre: pre, args: options};
		if (hasRefl(sch)) {
                    var l = [];
                    var k;
                    for (k=0; k < vrb.length; k++) {
		        l.push(vrb[k] + " się");
                    }
                    lex.lemma = l;
		}
		lexicalisation.push(lex);
            }
	} 
    } 

    display += getFormForLexicalisation(lexicalisation);

    display += "</div>";

    return display;
}

function getFormForLexicalisation(lexicalisation) {
    var options = [];
    var i;
    for (i = 0; i < lexicalisation.length; i++) {
	var perms = permute(lexicalisation[i].args);
	var j;
	for (j = 0; j < perms.length; j++) {
	    options.push({lemma: lexicalisation[i].lemma, pre: lexicalisation[i].pre, post: cartesian(perms[j])});
	}
    }
    result = lexicalisationForm(options);
    return result;
}

function permute(list) {
    var i;
    if (list.length == 0) {
        return [[]];
    } else {
	var result = [];
	for (i = 0; i < list.length; i++) {
	    var shortlist = list.slice();
	    shortlist.splice(i, 1);
	    var perms = permute(shortlist);
	    var j;
	    for (j = 0; j < perms.length; j++) {
		var tmp = perms[j];
		tmp.push(list[i]);
		result.push(tmp);
	    }
	}
        return result;
    }

}

function cartesian(llist) {
    if (llist.length == 0) {
        return [[]];
    }
    var result = [];
    var shortllist = llist.slice();
    shortllist.splice(shortllist.length - 1, 1);
    var carts = cartesian(shortllist);
    var i;
    for (i = 0; i < llist[llist.length - 1].length; i++) {
        var tail = llist[llist.length - 1][i];
        var heads = carts.slice();
        var j;
        for (j = 0; j < heads.length; j++) {
            var tmp = heads[j].slice();
            tmp.push(tail);
            result.push(tmp);
        }
    }
    return result;
}

function lexicalisationForm(lemmalist) {
    var i;
    var options = [];
    for (k = 0; k < lemmalist.length; k++) {
        var lemma = lemmalist[k].lemma;
        var pre = lemmalist[k].pre;
        var tokenised = lemmalist[k].post;
	var list;
	if (pre.length == 0) {
	    list = noSubjUnits(lemma, tokenised);
	} else {
	    list = subjUnits(pre, lemma, tokenised);
	}
        options = options.concat(list);
    }

    $.ajax({
        type: "POST",
        dataType: "json",
        url: ajax_get_mwes,
        data: {"options": JSON.stringify(options)},
        success: function(data){
            list = data.mwes;
        },
        async: false
    });

    var display = "";
    var i, j;
    for (i = 0; i < list.length; i++) {
        var included = false;
        for (j = 0; j < lexical_units.length; j++) {
            if (list[i].base == lexical_units[j].base && list[i].sense == lexical_units[j].sense) {
                included = true;
            }
        }
        if (!included) {
            display += "<input type = \"checkbox\" name = \"mwe\" value = \"" + list[i].base + '-' + list[i].sense + "_" + list[i].id + "_" + list[i].luid + "_" + list[i].sid + "\">" + list[i].base + '-' + list[i].sense + "<br\>";
        }
    }
    return display;
}

function noSubjUnits(lemmata, dependants) {
    var result = [];
    var i, j;
    for (i = 0; i < lemmata.length; i++) {
        if (dependants.length == 0) {
             result.push(lemmata[i]);
        } else {
            for (j = 0; j < dependants.length; j++) {
                if (dependants[j].length > 0) {
                    result.push(lemmata[i] + " " + dependants[j].join(" "));
                } else {
                    result.push(lemmata[i]);
                }
            }
        }
    }
    return result;
}

function subjUnits(pre, lemmata, dependants) {
    var result = [];
    var i, j;
    var temp = noSubjUnits(lemmata, dependants);
    i = decapitate(dependants);
    var pre2 = i.heads;
    var temp2 = noSubjUnits(lemmata, i.bodies);
    for (i = 0; i < pre.length; i++) {
        for (j = 0; j < temp.length; j++) {
            result.push(pre[i] + " " + temp[j]);
        }
        for (j = 0; j < pre2.length; j++) {
            result.push(pre[i] + " " + pre2[j] + " " + temp2[j]);
        }
    }
    return result;
}

function decapitate(llist) {
    var heads = [];
    var bodies = [];
    var i;
    for (i = 0; i < llist.length; i++) {
        if (llist[i].length > 0) {
            var body = llist[i].slice();
            var head = body[0];
            body.splice(0, 1);
            heads.push(head);
            bodies.push(body);
        }
    }
    return {heads: heads, bodies: bodies};
}


// get readable form of lexical unit
function getLexicalUnit(luid) {
    var i = indexOfId(lexical_units, luid);
    // alert("" + luid + " -> " + i);
    var lu = lexical_units[i];
    return lu.base + '-' + lu.sense;
}


function addPhraseologicalUnit(mwe, glossa, relation, to) {
    var lu = {base: mwe.split('-')[0], glossa: "" + glossa, definition: "", id: free_luid, luid: -1, refl: "false", glossa: glossa, pos: part_of_speech, sense: mwe.split('-')[1], relation: relation, to: to, location: ""};
    var operation = {operation: 'add_unit', unit:lu};
    lexical_units.push(lu);
    lexical_unit_examples[free_luid] = [];
    frames_operations.push(operation); 
    free_luid -= 1; 
    return (free_luid + 1);
}

function unlockPhraseologicalUnit(mwe) {
    var lu = {base: mwe.lu.split('-')[0], glossa: "", definition: "", id: mwe.id, luid: mwe.luid, refl: false, glossa: "", pos: part_of_speech, sense: mwe.lu.split('-')[1], relation: 2, to: -1, location: ""};
    lexical_units.push(lu);
    return mwe.id;
}

function addPhraseologicalUnits(frame_id, old_units, old_mwes, new_mwes, glossa, relation, to) {
    var i;
    var units = old_units.slice();
    for (i = 0; i < old_mwes.length; i++) {
        units.push(unlockPhraseologicalUnit(old_mwes[i]));
    }
    for (i = 0; i < new_mwes.length; i++) {
        units.push(addPhraseologicalUnit(new_mwes[i], glossa, relation, to));
    }
    changeUnits(frame_id, units);
}


function getPhraseologicalAlternations(frame_id) {
    var result = [];
    if (frame_content[frame_id].lemma.include) {
	var lem = frame_content[frame_id].lemma.csv_class;
	var i;
	for (i = 0; i < connected[lem].length; i++) {
            var ids = connected[lem][i].split('_');
            result.push(ids[1] + "_" + ids[7]);
	}
    } 
    return unique(result);
}

