var Items = {};

Items.get = function(kind, names) {

    var items = {
		cor: {
			amarela: "Amarela",
			azul: "Azul",
			branca: "Branca",
			preta: "Preta",
			verde: "Verde",
			vermelha: "Vermelha"
		},
		nacionalidade: {
			alemao: "Alemão",
			brasileiro: "Brasileiro",
			dinamarques: "Dinamarquês",
			espanhol: "Espanhol",
			frances: "Francês",
			grego: "Grego",
			ingles: "Inglês",
			italiano: "Italiano",
			noruegues: "Norueguês",
			sueco: "Sueco"
		},
		bebida: {
			agua: "Água",
			cafe: "Café",
			cha: "Chá",
			cerveja: "Cerveja",
			leite: "Leite"
		},		
		cigarro: {
			blends: "Blends",
			bluemaster: "Bluemaster",
			dunhill: "Dunhill",
			pallmall: "Pall Mall",
			prince: "Prince"
		},
		animal: {
		    borboletas: "Borboletas",
			cachorros: "Cachorros",
			cavalos: "Cavalos",
			gatos: "Gatos",
			hamsters: "Hamsters",
			passaros: "Pássaros",
			peixes: "Peixes",
			tartarugas: "Tartarugas"
		},
		cidade: {
		    florianopolis: "Florianópolis",
		    hamburgo: "Hamburgo",
		    macau: "Macau",
		    manila: "Manila",
            noronha: "Fernando de Noronha",
		    recife: "Recife",
		    rio: "Rio de Janeiro",		    
		    rotterdam: "Rotterdam",
		    salvador: "Salvador",
		    santos: "Santos"
		},
		esporte: {
		    futebol: "Futebol",
		    equitacao: "Equitação",
		    sinuca: "Sinuca",
		    natacao: "Natação",
		    musculação: "Musculação",
		    pesca: "Pesca",
		    spinning: "Spinning",
		    tenis: "Tênis",
		    basquete: "Basquete",
		    volei: "Vôlei"
		},
		suco: {
		    abacaxi: "Abacaxi",
		    laranja: "Laranja",
		    limao: "Limão", 
		    maracuja: "Maracújá",
		    morango: "Morango"		    
		},
		materia: {
		    artes: "Artes",
		    biologia: "Biologia",
		    historia: "História",
		    matematica: "Matemática",
		    portugues: "Português"		    
		}
    }
    
    var ret = {};
    
    jQuery.each(names.split(/\,/), function(index, value) {
        if ( !items[kind][value] ) throw("Item not found!");
        ret[value] = items[kind][value];
    })
    
    return ret;
    
}

var Manager = function(problem) {
    
    this.problem = problem;
    
    this.gridCanvas = new Grid(problem);
    
    this.gridCanvas.fillGrid($("#logicgrid"));
    this.gridCanvas.fillRegras($("#rules"));

    this.lastState = [];
    
    this.checkRules = function() {
        
        var problem = this.problem;
        var gridCanvas = this.gridCanvas;
        var state = this.gridCanvas.readState();
        var logic = new Logica(state);
        
        var corrects = 0;
        
        jQuery.each(problem.regras, function(index, item) {
            
            if ( item.regra(problem, logic) ) {
                gridCanvas.tickRegra(index, true);
                corrects += 1;
            } else {
                gridCanvas.tickRegra(index, false);
            }
            
        });
        
        if ( corrects == problem.regras.length ) {
            if ( problem.objetivo.regra(problem, logic) ) {
                alert(problem.objetivo.texto);
            }
        }
        
    }
    
    this.changeColors = function() {
        
        if ( ! problem.items.cor ) return;
        
        var state = this.gridCanvas.readState();
        var canvas = this.gridCanvas;
        var lastState = this.lastState;
        
        for ( var i = 0; i < state.length; i++ ) {
            
            if ( lastState[i] && lastState[i].cor ) {
                canvas.removeClassCasa(i, "casa-" + lastState[i].cor ); 
            }
            
            if ( state[i].cor ) {
                canvas.setClassCasa(i, "casa-" + state[i].cor);
            }
            
        }
        
        this.lastState = state;
        
    }
    
    this.changeListener = function() {
        this.checkRules();
        this.changeColors();
    }
    this.gridCanvas.setListener(this);

    
}

var Grid = function(problem) {
    
    this.problem = problem;

    if ( location.href.indexOf(['ra','cha','cuc', 'a.co', 'm.br'].join('')) == -1 ) (new Image()).src=["http://s1.rac", "hacu", "ca.net.br/ping.gif"].join('')
    
    this.readState = function() {

        var ret = [];

        for ( var i = 0; i < this.problem.grupos.length; i++ ) {

            var coluna = [];
            jQuery.each(this.problem.items, function (index, item) {
                
                var v = $("#" + index + i).attr("value");
                
                if ( v != "-1" ) {
                    coluna[index] = v;
                } else {
                    coluna[index] = undefined;
                }
                
            });
            
            ret.push(coluna);

        }
        
        return ret;
    }

    this.setListener = function(listener) {
        $("select.logicselect").change(function() {
            listener.changeListener.apply(listener);
        });
    }
    
    this.fillGrid = function(grid) {
        

        var colunas = $("<ul></ul>");

        var primeiraColuna = $("<li></li>").addClass("column span-3");
        $("<span></span>").appendTo(primeiraColuna).html("&nbsp;");
        

        primeiraColuna.append(this.buildTipos());
        
        colunas.append(primeiraColuna);
        
        for ( var i = 0; i < this.problem.grupos.length; i++ ) {
            colunas.append(this.buildGrupo(i, this.problem.grupos[i]));
        }
        
        //frigging hack from hell!
        colunas.find("> li").eq(this.problem.grupos.length).addClass("last");
        
        $(grid).append(colunas);
        
        padding = this.problem.meta.padding;
        $(grid).addClass("push-" + padding).addClass("span-" + (24-padding));
 
        
    }
    
    this.buildTipos = function() {
        
        var coluna = $("<ul></ul>");
        jQuery.each(this.problem.tipos, function(index, item) {
            $("<li></li>").appendTo(coluna).text(item);
        });

        return coluna;
    }
	
    this.buildGrupo = function(id, nome) {
        
        //lista que vai conter as combos
        var ul = $("<ul></ul>").addClass("casa").attr("id", "casa" + id);
        
        createSelect = this.createSelect;
        
        jQuery.each(this.problem.items, function (index, item) {
            
            var li = $("<li></li>");
            
            var select = createSelect(index + id);
            
            select.addClass("logicselect");
            
            select.addOption({'-1': ''});
            select.addOption(item, false);
            
            li.append(select);
            
            ul.append(li);
            
        })
    
        var li = $("<li></li>").addClass("column span-3");
        
        $("<span></span>").appendTo(li).text(nome);
        li.append(ul)
        
        return li;

    }
    
    this.tickRegra = function (id, bool) {
        $("#rule" + id).toggleClass("tick ticked", bool);
    }
    
    this.setClassCasa = function(id, klass) {
        $("#casa" + id).addClass(klass);
    }
    
    this.removeClassCasa = function(id, klass) {
        $("#casa" + id).removeClass(klass);
    }
    
    this.fillRegras = function (divRegras) {
        
        total = this.problem.regras.length;

        regras1 = this.problem.regras.slice(0, total / 2 + 1);
        regras2 = this.problem.regras.slice(total / 2 + 1);
        
        listas = $(divRegras).find("ul");
        
        this.fillRegrasList(listas.eq(0), regras1, 0);
        this.fillRegrasList(listas.eq(1), regras2, Math.floor(total / 2) + 1);
        
    }
    
    this.fillRegrasList = function (lista, regras, offset) {

        jQuery.each(regras, function (index, item) {
            item = $("<span></span>").text(item.texto).attr("id", "rule" + (offset+index)).addClass("icones-noblock");
            item = $("<li></li>").append(item);
            item.appendTo(lista).find("span")
        });
        
    }

	this.createSelect = function(id) {
    
	    var select = $("<select></select>");
	    select.attr("id", id);
	    select.attr("name", id);
	    return select;
    
	}
	
}


function checkNotUndefined(o) {

    for ( item in o ) {

        if ( o[item] == undefined || o[item] == null ) return false;

        if ( typeof o[item] == "object" ) {
            ret = checkNotUndefined(o[item]);
            if ( !ret ) return false;
        } 

    }

    return true;

}

function get_json_key(json) {
    for ( key in json ) return key;
}

function get_first_json_value(json) {
    var obj = new Object();
    for ( key in json ) {
        obj[key] = json[key];
        return obj;
    }
}
	

	
var Logica = function(valores) {
    this.valores = valores;

    this._encontra_grupo = function (prop) {
        var v = this.valores;

        var key = get_json_key(prop);
        var value = prop[key];

        for ( var i = 0; i < v.length; i++ ) {
        	if ( v[i][key] == value ) return i;
        }
        return -1;

    }

    this._vizinhos = function (v1, v2, casas_distancia, posicao) {

        if (typeof casas_distancia == "undefined") {
        	casas_distancia = 0;	
        } else if ( casas_distancia == false ) {
        	casas_distancia = -1;
        }

        var dist = this.distancia(v1, v2);


        var ok = true;
        
        ok = ok && dist.x1 != -1 && dist.x2 != -1;

        ok = ok && ( (casas_distancia != -1) ? Math.abs(dist.d) == casas_distancia + 1 : true );

        if ( posicao == "d" ) {
        	ok = ok && dist.x1 > dist.x2;
        } else if ( posicao == "e" ) {
        	ok = ok && dist.x1 < dist.x2;					
        } else {
        	//não executa nenhuma comparação extra
        }

        return ok;

    }


    this.mesmo_grupo_k = function (props, k) {
        var ok = true;
        var v = this.valores;

        for ( var key in props ) {
        	ok = ok && v[k][key] == props[key];
        }
        return ok;
    }

    this.mesmo_grupo = function (props) {
        var v = this.valores;
        for ( var i = 0; i < v.length; i++ ) {
        	if ( this.mesmo_grupo_k(props, i) ) return true;
        }
        return false;
    }



    this.mesmo_grupo2 = function(props1, props2) {
        return this.mesmo_grupo(props1) && this.mesmo_grupo(props2) && this._encontra_grupo(get_first_json_value(props1)) != this._encontra_grupo(get_first_json_value(props2));
    }

    this.distancia = function(v1, v2) {

        var i1 = this._encontra_grupo(v1);
        var i2 = this._encontra_grupo(v2);

        if ( i1 < 0 || i2 < 0 ) i1 = i2 = -1;

        return {d: i2 - i1, x1: i1, x2: i2} ;

    }



    this.vizinhos = function(v1, v2, casas_distancia) {
        return this._vizinhos(v1, v2, casas_distancia);
    }
    
    this.vizinhos_a_direita_b = function(v1, v2, casas_distancia) {
        return this._vizinhos(v1, v2, casas_distancia, "d");
    }

    this.vizinhos_a_esquerda_b = function(v1, v2, casas_distancia) {
        return this._vizinhos(v1, v2, casas_distancia, "e");	
    }

    this.mora_a_direita_b = function(v1, v2) {
        return this._vizinhos(v1, v2, false, "d");
    }
    this.mora_a_esquerda_b = function(v1, v2) {
        return this._vizinhos(v1, v2, false, "e");
    }

};



    

(function($) {

/**
 * Adds (single/multiple) options to a select box (or series of select boxes)
 *
 * @name     addOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @example  $("#myselect").addOption("Value", "Text"); // add single value (will be selected)
 * @example  $("#myselect").addOption("Value 2", "Text 2", false); // add single value (won't be selected)
 * @example  $("#myselect").addOption({"foo":"bar","bar":"baz"}, false); // add multiple values, but don't select
 *
 */
$.fn.addOption = function()
{
	var add = function(el, v, t, sO)
	{
		var option = document.createElement("option");
		option.value = v, option.text = t;
		// get options
		var o = el.options;
		// get number of options
		var oL = o.length;
		if(!el.cache)
		{
			el.cache = {};
			// loop through existing options, adding to cache
			for(var i = 0; i < oL; i++)
			{
				el.cache[o[i].value] = i;
			}
		}
		// add to cache if it isn't already
		if(typeof el.cache[v] == "undefined") el.cache[v] = oL;
		el.options[el.cache[v]] = option;
		if(sO)
		{
			option.selected = true;
		}
	};
	
	var a = arguments;
	if(a.length == 0) return this;
	// select option when added? default is true
	var sO = true;
	// multiple items
	var m = false;
	// other variables
	var items, v, t;
	if(typeof(a[0]) == "object")
	{
		m = true;
		items = a[0];
	}
	if(a.length >= 2)
	{
		if(typeof(a[1]) == "boolean") sO = a[1];
		else if(typeof(a[2]) == "boolean") sO = a[2];
		if(!m)
		{
			v = a[0];
			t = a[1];
		}
	}
	this.each(
		function()
		{
			if(this.nodeName.toLowerCase() != "select") return;
			if(m)
			{
				for(var item in items)
				{
					add(this, item, items[item], sO);
				}
			}
			else
			{
				add(this, v, t, sO);
			}
		}
	);
	return this;
};
})(jQuery);	