import java.util.*;

public class Cubo implements Comparable{
	
	private char[] prodotto;
	private boolean  marcato = false; 
	private int peso = 2;
	private int versioneS = 1; // 0: weight first (wd), 1: dimesnion first (dw)
	
	public Cubo(char[] prodotto, int versione) {
		this.versioneS = versione;
		this.prodotto = new char[prodotto.length];
		for (int i = 0; i< prodotto.length; i++) 
			this.prodotto[i] = prodotto[i];
	}
	
	
	public Cubo(int n, int versione) {
		this.prodotto = new char[n];
		this.versioneS = versione;
		for (int i = 0; i< prodotto.length; i++)
			this.prodotto[i] = '-';
	}
	
	public int getPeso() {
		return peso;
	}
	
	public int getVersione() {
		return versioneS;
	}
	
		
	public void setPeso(int p) {
		peso = p;
	}
	
	public boolean getMarca() {
		return marcato;
	}
		
	public void setMarca(boolean c) {
		this.marcato = c;
	}
	
	public char[] getProdotto() {
		return prodotto;
	}
			
	
	public int dim() {
		int dim = 0;
		for(int i = 0; i< this.prodotto.length; i++) {
			if (this.prodotto[i] == '-') dim++;
		}
		return dim;
	}
	
	public int match(Cubo c) {
		int match = 0;
		for(int i = 0; i < c.prodotto.length; i++) {
			if(this.prodotto[i] == '1' && c.prodotto[i]== '1') match++;
			else if(this.prodotto[i] == '0' && c.prodotto[i]== '0') match++;
		}
		return match;
	}
	
	public boolean equalTo(Cubo c) {
		if (c == null) return false;
		for(int i = 0; i < c.prodotto.length; i++) {
			if(this.prodotto[i] != c.prodotto[i]) return false;
		}
		return true;
	}
	
	public int compareTo(Object o) {
		Cubo c = (Cubo) o;
		if (versioneS== 0) {
			if (this.peso < c.peso) return -1;
			if (this.peso > c.peso) return 1; 
			if (this.dim() > c.dim()) return -1;
		    if (this.dim() < c.dim()) return 1;
		    return 0;
		}
		else if (versioneS == 1) {
			if (this.dim() > c.dim()) return -1;
		    if (this.dim() < c.dim()) return 1;
			if (this.peso < c.peso) return -1;
			if (this.peso > c.peso) return 1; 
		    return 0;
		}
		else  {
			if (this.dim() > c.dim()) return -1;
		    if (this.dim() < c.dim()) return 1;
		    else return 0;
		}
	}
	
	public int diff(Cubo c) {
		return (int) Math.abs(this.getPeso() - c.getPeso()); 
	}
	
	public Cubo intersezione(Cubo c) {
		int n = prodotto.length;
		char[] inter = new char[n];
		for(int i = 0; i < n; i++) {
			if (c.prodotto[i] == '0' && this.prodotto[i] == '1') return null;
			if (c.prodotto[i] == '1' && this.prodotto[i] == '0') return null;
			if (c.prodotto[i] == this.prodotto[i]) inter[i] = this.prodotto[i];
			if (c.prodotto[i] == '-') inter[i] = this.prodotto[i];
			else inter[i] = c.prodotto[i];
		}
		return new Cubo(inter, c.getVersione());
	}


	public int diff2(Cubo c) {
		return (int) Math.abs(this.dim() - c.dim()); 
	}
	
	public int frammenti(Cubo c) {
		return prodotto.length - this.dim() - this.match(c);
	}
	
	public String toString() {
		if (this == null) return null;
		String cubo = new String();
		for(int i = 0; i < this.prodotto.length; i++)
			cubo = cubo + prodotto[i];
		return cubo + " peso: " + peso + " dim: " + this.dim() +" marca: " + marcato;
	}
	
	public String prodottoToString() {
		if (this == null) return null;
		String cubo = new String();
		for(int i = 0; i < this.prodotto.length; i++)
			cubo = cubo + prodotto[i];
		return cubo;
	}
	
	public Cubo[] disjointSharp(Cubo c) {
		//spezzo this
		int m = c.frammenti(this);
		Cubo[] pezzi = new Cubo[m];
		int n = this.prodotto.length;
		int ctr = 0;
		int i = 0;
		while (ctr < m) {
			char[] prod = new char[n];
			if(c.prodotto[i] == '-' || this.prodotto[i] == c.prodotto[i]) {i++; continue;}
			for (int j = 0; j < n; j++) {
				if(j < i) {
					if(this.prodotto[j] == c.prodotto[j]) prod[j] = c.prodotto[j];
					else if(this.prodotto[j] == '0' || c.prodotto[j]== '0') prod[j] = '0';
					else if(this.prodotto[j] == '-') prod[j] = c.prodotto[j];
					else if(c.prodotto[j] == '-') prod[j] = this.prodotto[j];
				}
				else if(i == j) {
					char b = c.prodotto[j];
					if (b == '0') b = '1';
					else b = '0';
					if(this.prodotto[j] == b) prod[j] = b;
					else if(this.prodotto[j] == '0' || b == '0') prod[j] = '0';
					else if(this.prodotto[j] == '-') prod[j] = b;
				}  
				else prod[j] = this.prodotto[j];
			}
			pezzi[ctr] = new Cubo(prod, c.getVersione());
			pezzi[ctr].setMarca(true);
			i++;
			ctr++;
		}
		return pezzi;	
	}
	

	public boolean incluso(Cubo c) {
		Cubo inter = this.intersezione(c);
		if(inter == null) return false;
		if(this.equalTo(inter)) return true;
		else return false;
	}
	
	public boolean incluso(Pla pla) {
		for(int i = 0; i < pla.cubi.size(); i++) {
			if (this.incluso(pla.get(i))) return true;
		}
		return false;
	}
	
	public void peso(Pla pla) {
		boolean intersezione = false;
		int p = 0;
		for(int i = 0; i < pla.cubi.size(); i++) {
			Cubo a = pla.get(i);
			if (!this.equalTo(a) && this.intersezione(a) != null) {
				intersezione = true;
				p = p + this.frammenti(a) - 1;
			}
		}
		if (intersezione) this.peso = p;
		else this.peso = -1;
	}
	
	public void aggiornaPeso(Pla pla) {
		int p = 0;
		for(int i = 0; i < pla.cubi.size(); i++) {
			Cubo a = pla.get(i);
			if (!this.equalTo(a) && this.intersezione(a) != null) {
				if(a.getPeso() > 0) a.setPeso(a.getPeso()-1);
			}
		}
	}
	
}
	
	