package de.uni_hamburg.fs;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;


class ConceptImplTest {

    @BeforeEach
    void setUp() {
        TypeSystem.newInstance();
    }


    @Test
    void testConstructorWithNameAndExtensional() {
        // given
        String testName = "TestConcept";
        boolean extensional = true;

        // when
        ConceptImpl concept = new ConceptImpl(testName, extensional);

        // then
        assertThat(concept.getName()).isEqualTo(testName);
        assertThat(concept.isExtensional()).isTrue();
    }

    @Test
    void testGetName() {
        // given
        String testName = "namespace::conceptName";
        ConceptImpl concept = new ConceptImpl(testName);

        // when
        String name = concept.getName();
        String namespace = concept.getNamespace();
        String fullName = concept.getFullName();

        // then
        assertThat(name).isEqualTo("conceptName");
        assertThat(namespace).isEqualTo("namespace");
        assertThat(fullName).isEqualTo(testName);
    }

    @Test
    void testIsaRelationship() throws TypeException {
        // given
        ConceptImpl superConcept = new ConceptImpl("SuperConcept");
        ConceptImpl concept = new ConceptImpl("TestConcept");

        // when
        concept.addIsa(superConcept);

        // then
        assertThat(concept.isa(superConcept)).isTrue();
    }


    @Test
    void testAddAppropWithName() throws NoSuchFeatureException, TypeException {
        // given
        ConceptImpl concept = new ConceptImpl("TestConcept");
        Name featureName = new Name("testFeature");
        ParsedType mockType = mock(ParsedType.class);

        // when
        concept.addApprop(featureName, mockType);
        TypeSystem.instance().recalcDirectIsa();

        // then
        assertThat(concept.isApprop(featureName)).isTrue();
        assertThat(concept.appropParsedType(featureName)).isEqualTo(mockType);
    }

    @Test
    void testAddAppropWithString() throws NoSuchFeatureException, TypeException {
        // given
        ConceptImpl concept = new ConceptImpl("TestConcept");
        String featureString = "testFeature";
        ParsedType mockType = mock(ParsedType.class);

        // when
        concept.addApprop(featureString, mockType);
        TypeSystem.instance().recalcDirectIsa();

        // then
        Name featureName = new Name(featureString);
        assertThat(concept.isApprop(featureName)).isTrue();
        assertThat(concept.appropParsedType(featureName)).isEqualTo(mockType);
    }


    @Test
    void testIsNotAWithIncompatibleConcepts() throws TypeException {
        // given
        ConceptImpl concept1 = new ConceptImpl("Concept1");
        ConceptImpl concept2 = new ConceptImpl("Concept2");
        Partition sharedPartition = new Partition();

        // when
        sharedPartition.addConcept(concept1);
        sharedPartition.addConcept(concept2);

        // then
        assertThat(concept1.isNotA(concept2)).isTrue();
    }


}