/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.atlas.repository.store.graph.v1;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.atlas.RequestContextV1;
import org.apache.atlas.TestOnlyModule;
import org.apache.atlas.TestUtils;
import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.services.MetadataService;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.AtlasTypeUtil;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import javax.inject.Inject;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.atlas.TestUtils.NAME;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;

/**
 * Test automatic inverse reference updating in V1 (V2?) code path.
 *
 */
@Guice(modules = TestOnlyModule.class)
public abstract class InverseReferenceUpdateV1Test {

    @Inject
    AtlasTypeRegistry typeRegistry;

    @Inject
    AtlasTypeDefStore typeDefStore;

    AtlasEntityStore entityStore;

    @Inject
    MetadataService metadataService;

    @Inject
    DeleteHandlerV1 deleteHandler;

    private AtlasEntitiesWithExtInfo deptEntity;

    AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);

    protected Map<String, AtlasObjectId> nameIdMap = new HashMap<>();

    protected abstract DeleteHandlerV1 getDeleteHandler(AtlasTypeRegistry typeRegistry);

    @BeforeClass
    public void setUp() throws Exception {
        metadataService = TestUtils.addSessionCleanupWrapper(metadataService);
        new GraphBackedSearchIndexer(typeRegistry);

        AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineDeptEmployeeTypes(),
                                                              TestUtilsV2.defineInverseReferenceTestTypes()
                                                            };

        for (AtlasTypesDef typesDef : testTypesDefs) {
            AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);

            if (!typesToCreate.isEmpty()) {
                typeDefStore.createTypesDef(typesToCreate);
            }
        }

        deptEntity = TestUtilsV2.createDeptEg2();
        DeleteHandlerV1 deleteHandler = getDeleteHandler(typeRegistry);
        entityStore = new AtlasEntityStoreV1(deleteHandler, typeRegistry, mockChangeNotifier);
        init();
        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(deptEntity), false);
        for (AtlasEntityHeader entityHeader : response.getCreatedEntities()) {
            nameIdMap.put((String)entityHeader.getAttribute(NAME), AtlasTypeUtil.getAtlasObjectId(entityHeader));
        }
    }

    @AfterClass
    public void clear() {
        AtlasGraphProvider.cleanup();
    }

    @BeforeMethod
    public void init() throws Exception {
        RequestContextV1.clear();
    }

    @Test
    public void testInverseReferenceAutoUpdate_NonComposite_OneToMany() throws Exception {
        AtlasObjectId juliusId = nameIdMap.get("Julius");

        // Change Max's Employee.manager reference to Julius and apply the change as a partial update.
        // This should also update Julius to add Max to the inverse Manager.subordinates reference.
        AtlasEntity maxEntityForUpdate = new AtlasEntity(TestUtilsV2.EMPLOYEE_TYPE);
        maxEntityForUpdate.setAttribute("manager", juliusId);
        AtlasEntityType employeeType = typeRegistry.getEntityTypeByName(TestUtilsV2.EMPLOYEE_TYPE);
        Map<String, Object> uniqAttributes = Collections.<String, Object>singletonMap("name", "Max");
        EntityMutationResponse updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
        List<AtlasEntityHeader> partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
        // 3 entities should have been updated:
        // * Max to change the Employee.manager reference
        // * Julius to add Max to Manager.subordinates
        // * Jane to remove Max from Manager.subordinates
        assertEquals(partialUpdatedEntities.size(), 3);

        AtlasObjectId maxId = nameIdMap.get("Max");
        String janeGuid = nameIdMap.get("Jane").getGuid();
        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), juliusId.getGuid(), janeGuid));
        AtlasEntity storedEntity = storedEntities.getEntity(maxId.getGuid());
        verifyReferenceValue(storedEntity, "manager", juliusId.getGuid());
        storedEntity = storedEntities.getEntity(juliusId.getGuid());
        verifyReferenceList(storedEntity, "subordinates", ImmutableList.of(maxId));
        storedEntity = storedEntities.getEntity(janeGuid);
        verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(storedEntity);
    }

    protected abstract void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception;

    @Test
    public void testInverseReferenceAutoUpdate_NonCompositeManyToOne() throws Exception {
        AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
        AtlasEntity a1 = new AtlasEntity("A");
        a1.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity a2 = new AtlasEntity("A");
        a2.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity a3 = new AtlasEntity("A");
        a3.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity b = new AtlasEntity("B");

        b.setAttribute(NAME, TestUtils.randomString());
        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
        atlasEntitiesWithExtInfo.addEntity(a1);
        atlasEntitiesWithExtInfo.addEntity(a2);
        atlasEntitiesWithExtInfo.addEntity(a3);
        atlasEntitiesWithExtInfo.addEntity(b);
        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);

        AtlasEntity bForPartialUpdate = new AtlasEntity("B");
        bForPartialUpdate.setAttribute("manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
        init();
        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
        // Verify 3 entities were updated:
        // * set b.manyA reference to a1 and a2
        // * set inverse a1.oneB reference to b
        // * set inverse a2.oneB reference to b
        assertEquals(partialUpdatedEntities.size(), 3);
        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
        AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
        verifyReferenceValue(storedEntity, "oneB", b.getGuid());

        storedEntity = storedEntities.getEntity(a2.getGuid());
        verifyReferenceValue(storedEntity, "oneB", b.getGuid());

        storedEntity = storedEntities.getEntity(b.getGuid());
        verifyReferenceList(storedEntity, "manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));

        bForPartialUpdate.setAttribute("manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a3)));
        init();
        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
        partialUpdatedEntities = response.getPartialUpdatedEntities();
        // Verify 4 entities were updated:
        // * set b.manyA reference to a3
        // * set inverse a3.oneB reference to b
        // * disconnect inverse a1.oneB reference to b
        // * disconnect inverse a2.oneB reference to b
        assertEquals(partialUpdatedEntities.size(), 4);

        init();
        storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), a3.getGuid(), b.getGuid()));
        verifyReferenceValue(storedEntities.getEntity(a3.getGuid()), "oneB", b.getGuid());

        verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(a2.getGuid()),
            storedEntities.getEntity(a3.getGuid()), storedEntities.getEntity(b.getGuid()));
    }

    protected abstract void verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b);

    @Test
    public void testInverseReferenceAutoUpdate_NonComposite_OneToOne() throws Exception {
        AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
        AtlasEntity a1 = new AtlasEntity("A");
        a1.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity a2 = new AtlasEntity("A");
        a2.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity b = new AtlasEntity("B");
        b.setAttribute(NAME, TestUtils.randomString());
        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
        atlasEntitiesWithExtInfo.addEntity(a1);
        atlasEntitiesWithExtInfo.addEntity(a2);
        atlasEntitiesWithExtInfo.addEntity(b);
        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);

        AtlasEntity bForPartialUpdate = new AtlasEntity("B");
        bForPartialUpdate.setAttribute("a", AtlasTypeUtil.getAtlasObjectId(a1));
        init();
        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
        // Verify 2 entities were updated:
        // * set b.a reference to a1
        // * set inverse a1.b reference to b
        assertEquals(partialUpdatedEntities.size(), 2);
        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b.getGuid()));
        AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
        verifyReferenceValue(storedEntity, "b", b.getGuid());
        storedEntity = storedEntities.getEntity(b.getGuid());
        verifyReferenceValue(storedEntity, "a", a1.getGuid());

        // Update b.a to reference a2.
        bForPartialUpdate.setAttribute("a", AtlasTypeUtil.getAtlasObjectId(a2));
        init();
        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
        partialUpdatedEntities = response.getPartialUpdatedEntities();
        // Verify 3 entities were updated:
        // * set b.a reference to a2
        // * set a2.b reference to b
        // * disconnect a1.b reference
        assertEquals(partialUpdatedEntities.size(), 3);
        storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
        storedEntity = storedEntities.getEntity(a2.getGuid());
        verifyReferenceValue(storedEntity, "b", b.getGuid());
        storedEntity = storedEntities.getEntity(b.getGuid());
        verifyReferenceValue(storedEntity, "a", a2.getGuid());
        storedEntity = storedEntities.getEntity(a1.getGuid());
        Object refValue = storedEntity.getAttribute("b");
        verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(b.getGuid()));
    }

    protected abstract void verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b);

    @Test
    public void testInverseReferenceAutoUpdate_NonComposite_ManyToMany() throws Exception {
        AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
        AtlasEntity a1 = new AtlasEntity("A");
        a1.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity a2 = new AtlasEntity("A");
        a2.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity a3 = new AtlasEntity("A");
        a3.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity b1 = new AtlasEntity("B");
        b1.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity b2 = new AtlasEntity("B");
        b2.setAttribute(NAME, TestUtils.randomString());
        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
        atlasEntitiesWithExtInfo.addEntity(a1);
        atlasEntitiesWithExtInfo.addEntity(a2);
        atlasEntitiesWithExtInfo.addEntity(a3);
        atlasEntitiesWithExtInfo.addEntity(b1);
        atlasEntitiesWithExtInfo.addEntity(b2);
        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);

        AtlasEntity b1ForPartialUpdate = new AtlasEntity("B");
        b1ForPartialUpdate.setAttribute("manyToManyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
        init();
        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b1.getAttribute(NAME)), new AtlasEntityWithExtInfo(b1ForPartialUpdate));
        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
        assertEquals(partialUpdatedEntities.size(), 3);
        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b1.getGuid()));
        AtlasEntity storedEntity = storedEntities.getEntity(b1.getGuid());
        verifyReferenceList(storedEntity, "manyToManyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
        storedEntity = storedEntities.getEntity(a1.getGuid());
        verifyReferenceList(storedEntity, "manyB", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(b1)));
        storedEntity = storedEntities.getEntity(a2.getGuid());
        verifyReferenceList(storedEntity, "manyB", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(b1)));
    }

    @Test
    public void testInverseReferenceAutoUpdate_Map() throws Exception {
        AtlasEntity a1 = new AtlasEntity("A");
        a1.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity b1 = new AtlasEntity("B");
        b1.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity b2 = new AtlasEntity("B");
        b2.setAttribute(NAME, TestUtils.randomString());
        AtlasEntity b3 = new AtlasEntity("B");
        b3.setAttribute(NAME, TestUtils.randomString());
        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
        atlasEntitiesWithExtInfo.addEntity(a1);
        atlasEntitiesWithExtInfo.addEntity(b1);
        atlasEntitiesWithExtInfo.addEntity(b2);
        atlasEntitiesWithExtInfo.addEntity(b3);
        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);

        AtlasEntityType aType = typeRegistry.getEntityTypeByName("A");
        AtlasEntity aForPartialUpdate = new AtlasEntity("A");
        aForPartialUpdate.setAttribute("mapToB", ImmutableMap.<String, AtlasObjectId>of("b1", AtlasTypeUtil.getAtlasObjectId(b1), "b2", AtlasTypeUtil.getAtlasObjectId(b2)));
        init();
        response = entityStore.updateByUniqueAttributes(aType, Collections.<String, Object>singletonMap(NAME, a1.getAttribute(NAME)), new AtlasEntityWithExtInfo(aForPartialUpdate));
        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
        // Verify 3 entities were updated:
        // * set a1.mapToB to "b1"->b1, "b2"->b2
        // * set b1.mappedFromA to a1
        // * set b2.mappedFromA to a1
        assertEquals(partialUpdatedEntities.size(), 3);
        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b2.getGuid(), b1.getGuid()));
        AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
        Object value = storedEntity.getAttribute("mapToB");
        assertTrue(value instanceof Map);
        Map<String, AtlasObjectId> refMap = (Map<String, AtlasObjectId>) value;
        assertEquals(refMap.size(), 2);
        AtlasObjectId referencedEntityId = refMap.get("b1");
        assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b1));
        referencedEntityId = refMap.get("b2");
        assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b2));
        storedEntity = storedEntities.getEntity(b1.getGuid());
        verifyReferenceValue(storedEntity, "mappedFromA", a1.getGuid());
        storedEntity = storedEntities.getEntity(b2.getGuid());
        verifyReferenceValue(storedEntity, "mappedFromA", a1.getGuid());

        aForPartialUpdate.setAttribute("mapToB", ImmutableMap.<String, AtlasObjectId>of("b3", AtlasTypeUtil.getAtlasObjectId(b3)));
        init();
        response = entityStore.updateByUniqueAttributes(aType, Collections.<String, Object>singletonMap(NAME, a1.getAttribute(NAME)), new AtlasEntityWithExtInfo(aForPartialUpdate));
        partialUpdatedEntities = response.getPartialUpdatedEntities();
        // Verify 4 entities were updated:
        // * set a1.mapToB to "b3"->b3
        // * set b3.mappedFromA to a1
        // * disconnect b1.mappedFromA
        // * disconnect b2.mappedFromA
        assertEquals(partialUpdatedEntities.size(), 4);
        storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b2.getGuid(), b1.getGuid(), b3.getGuid()));
        AtlasEntity storedB3 = storedEntities.getEntity(b3.getGuid());
        verifyReferenceValue(storedB3, "mappedFromA", a1.getGuid());
        verify_testInverseReferenceAutoUpdate_Map(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(b1.getGuid()), storedEntities.getEntity(b2.getGuid()), storedB3);
    }

    protected abstract void verify_testInverseReferenceAutoUpdate_Map(AtlasEntity a1, AtlasEntity b1, AtlasEntity b2, AtlasEntity b3);

    protected void verifyReferenceValue(AtlasEntity entity, String refName, String expectedGuid) {
        Object refValue = entity.getAttribute(refName);
        if (expectedGuid == null) {
            assertNull(refValue);
        }
        else {
            assertTrue(refValue instanceof AtlasObjectId);
            AtlasObjectId referencedObjectId = (AtlasObjectId) refValue;
            assertEquals(referencedObjectId.getGuid(), expectedGuid);
        }
    }

    protected void verifyReferenceList(AtlasEntity entity, String refName, List<AtlasObjectId> expectedValues) {
        Object refValue = entity.getAttribute(refName);
        assertTrue(refValue instanceof List);
        List<AtlasObjectId> refList = (List<AtlasObjectId>) refValue;
        assertEquals(refList.size(), expectedValues.size());
        if (expectedValues.size() > 0) {
            assertTrue(refList.containsAll(expectedValues));
        }
    }
}
