import utest.Assert;
import utest.Test;
import source.Mocodo;
import model.Set;
import model.Field;
import transform.DiagramToUML;

class TestDiagramToUML extends Test {
	//default visibility, getters/setters
	public function test01_Default() {
		var mocodoStr = "Ent1: ent1Id [counter], ent1F1 [varchar(100)]\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		var c = diagram.getObj("Ent1");
		Assert.equals(Field.ACCESS_PROTECTED, c.fields[0].visibility);
		Assert.equals(false, c.fields[1].isStatic);
		Assert.equals(0, c.methods.length);
		Assert.equals(4, c.accessors.length);
		Assert.equals("getEnt1Id", c.accessors[0].name);
		Assert.equals("Int", c.accessors[0].type);
		Assert.equals(Field.ACCESS_PUBLIC, c.accessors[0].visibility);
		Assert.equals(0, c.accessors[0].params.length);
		Assert.equals("setEnt1Id", c.accessors[1].name);
		Assert.equals(1, c.accessors[3].params.length);
		Assert.equals("ent1F1", c.accessors[3].params[0].name);
		Assert.equals("String", c.accessors[3].params[0].type);
	}

	//visibility 
	public function test02_Visibility() {
		var mocodoStr = "Ent1: +ent1Id, -ent1F1, ~ent1SF1, ~#ent1SF2\n";
		var diagram = Mocodo.load(mocodoStr);
		var c = diagram.getObj("Ent1");
		DiagramToUML.transform(diagram);
		Assert.equals(Field.ACCESS_PUBLIC, c.fields[0].visibility);
		Assert.equals(Field.ACCESS_PRIVATE, c.fields[1].visibility);
		Assert.equals(Field.ACCESS_PROTECTED, c.fields[2].visibility);
		Assert.equals(Field.ACCESS_PROTECTED, c.fields[3].visibility);
		Assert.equals(true, c.fields[2].isStatic);
		Assert.equals(true, c.fields[3].isStatic);
		Assert.equals(2, c.accessors.length);
	}

	//methods 
	public function test03_Methods() {
		var mocodoStr = "Ent1: ent1Id [counter], ent1F1 [varchar(100)]\n" +
						"Ent1(): ent1M1(ent1Id) [INT], #~ent1M2(ent1F1, noEnt1F1 [INT], noEnt1F2), ent1M3 ()\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		var c = diagram.getObj("Ent1");
		Assert.equals(3, c.methods.length);

		Assert.equals("ent1M1", c.methods[0].className);
		Assert.equals("Int", c.methods[0].classType);
		Assert.equals(Field.ACCESS_PUBLIC, c.methods[0].visibility);
		Assert.equals(false, c.methods[0].isStatic);
		Assert.equals(1, c.methods[0].params.length);
		Assert.equals("ent1Id", c.methods[0].params[0].className);
		Assert.equals("Int", c.methods[0].params[0].classType);

		Assert.equals(Field.ACCESS_PROTECTED, c.methods[1].visibility);
		Assert.equals(true, c.methods[1].isStatic);
		Assert.equals("", c.methods[1].classType);
		Assert.equals(3, c.methods[1].params.length);
		Assert.equals("ent1F1", c.methods[1].params[0].className);
		Assert.equals("String", c.methods[1].params[0].classType);
		Assert.equals("noEnt1F1", c.methods[1].params[1].className);
		Assert.equals("Int", c.methods[1].params[1].classType);
		Assert.equals("noEnt1F2", c.methods[1].params[2].className);
		Assert.equals("String", c.methods[1].params[2].classType);

		Assert.equals("ent1M3", c.methods[2].className);
		Assert.equals(0, c.methods[2].params.length);
		Assert.equals("", c.methods[2].type);
	}

	//navigation
	public function test04_Nav_01_1N() {
		var mocodoStr = "Ent1: ent1Id, ent1F1\n" +
						"Ent2: ent2Id, ent2F1\n" +
						"Ent1Ent2, 01 Ent1, 0N Ent2\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		var c1 = diagram.getObj("Ent1");
		Assert.equals(1, c1.navFields.length);
		Assert.equals("ent2", c1.navFields[0].className);
		Assert.equals("Ent2", c1.navFields[0].classType);
		Assert.equals(6, c1.accessors.length);
		var c2 = diagram.getObj("Ent2");
		Assert.equals(1, c2.navFields.length);
		Assert.equals("ent1s", c2.navFields[0].className);
		Assert.equals("Array<Ent1>", c2.navFields[0].classType);
	}

	public function test04_Nav_02_1NarrowRole() {
		var mocodoStr = "Ent1: ent1Id, ent1F1\n" +
						"Ent2: ent2Id, ent2F1\n" +
						"Ent1Ent2, 01 Ent1, +0N> [role] Ent2\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		var c1 = diagram.getObj("Ent1");
		Assert.equals(1, c1.navFields.length);
		Assert.equals("role", c1.navFields[0].className);
		Assert.equals("Ent2", c1.navFields[0].classType);
		Assert.equals(Field.ACCESS_PUBLIC, c1.navFields[0].visibility);
		var c2 = diagram.getObj("Ent2");
		Assert.equals(0, c2.navFields.length);
	}

	public function test04_Nav_03_NNassoc() {
		var mocodoStr = "ent1: ent1Id, ent1F1\n" + //try without first letter capitalized
						"Ent2: ent2Id, ent2F1\n" +
						"Ent1Ent2, 0N ent1, 0N [ent2RoleName] Ent2\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		var c1 = diagram.getObj("ent1");
		Assert.equals(1, c1.navFields.length);
		Assert.equals("ent2RoleName", c1.navFields[0].className);
		Assert.equals("Array<Ent2>", c1.navFields[0].classType);
		var c2 = diagram.getObj("Ent2");
		Assert.equals(1, c2.navFields.length);
		Assert.equals("ent1s", c2.navFields[0].className);
		Assert.equals("Array<Ent1>", c2.navFields[0].classType);
	}

	public function test04_Nav_04_classAssoc() {
		var mocodoStr = "Ent1: ent1Id, ent1F1\n" +
						"Ent2: ent2Id, ent2F1\n" +
						"Ent1Ent2, 0N Ent1, 0N [ent2RoleName] Ent2: Ent1Ent2F1\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		Assert.equals(0, diagram.getObj("Ent1").navFields.length);
		Assert.equals(0, diagram.getObj("Ent2").navFields.length);
		var c = diagram.getObj("Ent1Ent2");
		Assert.equals("ent1", c.navFields[0].className);
		Assert.equals("Ent1", c.navFields[0].classType);
		Assert.equals("ent2RoleName", c.navFields[1].className);
		Assert.equals("Ent2", c.navFields[1].classType);
	}
	//constructor
	public function test05_constructor() {
		var mocodoStr = "Ent1: ent1Id [COUNTER], ent1F1\n" +
						"Ent2: ent2Id, ent2F1\n" +
						"Ent3: ent3Id, ent3F1\n" +
						"Ent1Ent2, 0N Ent1, 0N Ent2: ent1ent2F1 [Unknown]\n" +
						"Ent2Ent3, 0N Ent2, 0N Ent3\n" +
						"Ent1Ent3, 0N Ent1, 01 Ent3\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		var c1 = diagram.getObj("Ent1");
		Assert.equals(2, c1.constructors[0].params.length);
		Assert.equals("ent1Id", c1.constructors[0].params[0].className);
		Assert.equals("Int", c1.constructors[0].params[0].classType);
		Assert.equals("ent1F1", c1.constructors[0].params[1].className);
		Assert.equals("String", c1.constructors[0].params[1].classType);
		var c3 = diagram.getObj("Ent3");
		Assert.equals(3, c3.constructors[0].params.length);
		Assert.equals("ent1", c3.constructors[0].params[2].className);
		Assert.equals("Ent1", c3.constructors[0].params[2].classType);
		var c12 = diagram.getObj("Ent1Ent2");
		Assert.equals(3, c12.constructors[0].params.length);
		Assert.equals("ent1ent2F1", c12.constructors[0].params[0].className);
		Assert.equals("Unknown", c12.constructors[0].params[0].classType);
		Assert.equals("ent1", c12.constructors[0].params[1].className);
		Assert.equals("Ent1", c12.constructors[0].params[1].classType);
		Assert.equals("ent2", c12.constructors[0].params[2].className);
		Assert.equals("Ent2", c12.constructors[0].params[2].classType);
		var c13 = diagram.getObj("Ent2Ent3");
		Assert.equals(null, c13.constructors[0]);
	}
	public function test06_subclassConstructor() {
		var mocodoStr = "Ent1: ent1Id, ent1F1\n" +
						"Ent2: ent2F1\n" +
						"/\\ Ent1 - Ent2\n";
		var diagram = Mocodo.load(mocodoStr);
		DiagramToUML.transform(diagram);
		var c2 = diagram.getObj("Ent2");
		Assert.equals(3, c2.constructors[0].params.length);
		Assert.equals("ent1Id", c2.constructors[0].params[0].className);
		Assert.equals("ent1F1", c2.constructors[0].params[1].className);
		Assert.equals("ent2F1", c2.constructors[0].params[2].className);
	}
}
