package de.renew.gui.fs;

import junit.framework.TestCase;

import de.renew.formalism.fs.ShadowConcept;
import de.renew.simulatorontology.shadow.ShadowNet;
import de.renew.simulatorontology.shadow.ShadowNetSystem;


public class ConceptFigureTest extends TestCase {
    ShadowNet shadowNet;
    private static final String stereotype1 = "<<stereotype>>";
    private static final String stereotype2 = "«stereotype»";
    private static final String documentation1 = "/**\nShort documentation\n*/";
    private static final String documentation2 =
        "/**Longer documentation\n with arbitrary   whitespaces \n and characters #%/§<<>>*/";
    private static final String annotation1 = "@SimpleAnnotation";
    private static final String annotation2 = "@ComplexAnnotation(name=\"name\")";
    private static final String conceptName = "concept-name";
    private static final String slot1 = "slot1: type1";
    private static final String slot2 = "slot-2: Type-2";
    private static String conceptDeclaration1;
    private static String conceptDeclaration2;
    private static String conceptDeclaration3;
    private static String conceptDeclaration4;
    private static String slotDeclaration1;
    private static String slotDeclaration2;
    private static String implementationDescription;

    public void setUp() {
        shadowNet = new ShadowNet("Shadow net", new ShadowNetSystem());

        conceptDeclaration1 = conceptName;
        conceptDeclaration2 = stereotype1 + "\n" + conceptName + "\n";
        conceptDeclaration3 = stereotype2 + "\n" + documentation1 + "\n" + conceptName;
        conceptDeclaration4 =
            stereotype1 + "\n" + documentation2 + "\n" + annotation1 + "\n" + conceptName;
        slotDeclaration1 = stereotype1 + "\n" + annotation1 + "\n" + conceptName + "\n"
            + documentation1 + "\n" + annotation2 + "\n" + slot1 + "\n" + slot2 + "\n" + annotation1
            + "\n" + annotation2 + "\n" + slot2;
        slotDeclaration2 = conceptName + "\n" + "\n" + slot1 + "\n" + "\n" + slot2;
        implementationDescription = "de.renew.gui.fs.ConceptFigure";
    }

    /**
     *  Test conceptDeclaration1
     */
    public void testConceptDeclaration1() {
        ConceptFigure cf = new ConceptFigure();

        cf.setText(conceptDeclaration1);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(conceptName, sc.getName());
        assertEquals("", sc.getApprop());
        assertEquals("", sc.getStereotype());
        assertEquals("", sc.getConceptDocumentation());
        assertEquals("", sc.getConceptAnnotation());
        assertEquals("", String.join("", sc.getSlotDocumentation()));
        assertEquals("", String.join("", sc.getSlotAnnotation()));
    }

    /**
     *  Test conceptDeclaration2
     */
    public void testConceptDeclaration2() {
        ConceptFigure cf = new ConceptFigure();

        cf.setText(conceptDeclaration2);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(stereotype1 + "\n" + conceptName, sc.getName());
        assertEquals("", sc.getApprop());
        assertEquals(stereotype1, sc.getStereotype());
        assertEquals("", sc.getConceptDocumentation());
        assertEquals("", sc.getConceptAnnotation());
        assertEquals("", String.join("", sc.getSlotDocumentation()));
        assertEquals("", String.join("", sc.getSlotAnnotation()));
    }

    /**
     *  Test conceptDeclaration3
     */
    public void testConceptDeclaration3() {
        ConceptFigure cf = new ConceptFigure();
        cf.setText(conceptDeclaration3);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(stereotype2 + "\n" + conceptName, sc.getName());
        assertEquals("", sc.getApprop());
        assertEquals(stereotype2, sc.getStereotype());
        assertEquals(
            documentation1.substring("/**".length(), documentation1.length() - "*/\n".length())
                .trim(),
            sc.getConceptDocumentation());
        assertEquals("", sc.getConceptAnnotation());
        assertEquals("", String.join("", sc.getSlotDocumentation()));
        assertEquals("", String.join("", sc.getSlotAnnotation()));
    }

    /**
     *  Test conceptDeclaration4
     */
    public void testConceptDeclaration4() {
        ConceptFigure cf = new ConceptFigure();

        cf.setText(conceptDeclaration4);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(stereotype1 + "\n" + conceptName, sc.getName());
        assertEquals("", sc.getApprop());
        assertEquals(stereotype1, sc.getStereotype());
        assertEquals(
            documentation2.substring("/**".length(), documentation2.length() - "*/\n".length())
                .trim(),
            sc.getConceptDocumentation());
        assertEquals(annotation1 + "\n", sc.getConceptAnnotation());
        assertEquals("", String.join("", sc.getSlotDocumentation()));
        assertEquals("", String.join("", sc.getSlotAnnotation()));
    }

    /**
     *  Test slotDeclaration1
     */
    public void testSlotDeclaration1() {
        ConceptFigure cf = new ConceptFigure();

        cf.setText(slotDeclaration1);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(stereotype1 + "\n" + conceptName, sc.getName());
        assertEquals(slot1 + "\n" + slot2 + "\n" + slot2, sc.getApprop());
        assertEquals(stereotype1, sc.getStereotype());
        assertEquals("", sc.getConceptDocumentation());
        assertEquals(annotation1 + "\n", sc.getConceptAnnotation());
        String doc = documentation1
            .substring("/**".length(), documentation1.length() - "*/\n".length()).trim();
        assertEquals(doc, String.join("", sc.getSlotDocumentation()));
        assertEquals(annotation2 + "\n", sc.getSlotAnnotation().get(0));
        assertEquals(annotation1 + "\n" + annotation2 + "\n", sc.getSlotAnnotation().get(2));
    }

    /**
     *  Test slotDeclaration2
     */
    public void testSlotDeclaration2() {
        ConceptFigure cf = new ConceptFigure();
        cf.setText(slotDeclaration2);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(conceptName, sc.getName());
        assertEquals(slot1 + "\n" + "\n" + slot2, sc.getApprop());
    }


    /**
     *  Test generated implementation description
     */
    public void testImplementationDescription() {
        ConceptFigure cf = new ConceptFigure();

        cf.setText(implementationDescription);

        String expectedFigureTextPrefix =
            "ConceptFigure\nshadow: de.renew.simulatorontology.shadow.ShadowNetElement {readOnly}";

        assertEquals(
            expectedFigureTextPrefix, cf.getText().substring(0, expectedFigureTextPrefix.length()));

        String s = "Concept\n" + "\n" + "-superclass: String {readOnly}\n"
            + "+name: String {readOnly}\n" + "_annotation: String {readOnly}\n"
            + "isCommon: boolean {readOnly}\n" + "isPredicate: boolean {readOnly}\n"
            + "isAgentAction: boolean {readOnly}\n" + "directSlots: java.util.List {readOnly}\n"
            + "documentation: String {readOnly}\n" + "allSuperconcepts: java.util.List {readOnly}\n"
            + "inheritedSlots: java.util.List {readOnly}\n"
            + "hasRequiredSlotConstructor: boolean {readOnly}\n" + "constName: String {readOnly}\n"
            + "isAbstract: boolean {readOnly}\n" + "javaName: String {readOnly}\n"
            + "shortPackage: String {readOnly}\n" + "isSubconcept: boolean {readOnly}\n"
            + "superconcept: Concept {readOnly}\n" + "ontology: Ontology {readOnly}\n"
            + "allSlots: java.util.List {readOnly}\n" + "requiredSlots: java.util.List {readOnly}\n"
            + "hasAllSlotConstructor: boolean {readOnly}\n"
            + "hasDocumentation: boolean {readOnly}\n" + "\n"
            + "parameterList(java.util.List): String\n" + "getIsSubtypeOf(String): boolean\n"
            + "addSlot(Slot)\n" + "nullableParameterList(java.util.List): String\n"
            + "setAbstract()\n" + "recalc()\n";

        cf.setText(s);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(cf.getText(), s);
    }

    /**
     *  Test access statement
     */
    public void testAccessStatement() {
        ConceptFigure cf = new ConceptFigure();
        String s = "RMT_Metamodel::model";
        cf.setText(s);
        ShadowConcept sc = (ShadowConcept) cf.buildShadow(shadowNet);
        assertEquals(cf.getName(), s);
    }
}
