/**
 * 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.graph;

import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasException;
import org.apache.atlas.TestUtils;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.typesystem.IReferenceableInstance;
import org.apache.atlas.typesystem.IStruct;
import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.typesystem.exception.EntityNotFoundException;
import org.apache.atlas.typesystem.exception.NullRequiredAttributeException;
import org.apache.atlas.typesystem.types.TypeSystem;
import org.testng.Assert;

import java.util.List;
import java.util.Map;

import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.fail;
import static org.testng.AssertJUnit.assertNotNull;

public class GraphBackedRepositoryHardDeleteTest extends GraphBackedMetadataRepositoryDeleteTestBase {
    @Override
    DeleteHandler getDeleteHandler(TypeSystem typeSystem) {
        return new HardDeleteHandler(typeSystem);
    }

    @Override
    protected void assertTestDeleteEntityWithTraits(String guid) {
        //entity is deleted. So, no assertions
    }

    @Override
    protected void assertTableForTestDeleteReference(String tableId) {
        //entity is deleted. So, no assertions
    }

    @Override
    protected void assertColumnForTestDeleteReference(ITypedReferenceableInstance tableInstance) throws AtlasException {
        List<ITypedReferenceableInstance> columns =
                (List<ITypedReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
        assertNull(columns);
    }

    @Override
    protected void assertProcessForTestDeleteReference(ITypedReferenceableInstance processInstance) throws Exception {
        //assert that outputs is empty
        ITypedReferenceableInstance newProcess =
                repositoryService.getEntityDefinition(processInstance.getId()._getId());
        assertNull(newProcess.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS));
    }

    @Override
    protected void assertEntityDeleted(String id) throws Exception {
        try {
            repositoryService.getEntityDefinition(id);
            fail("Expected EntityNotFoundException");
        } catch(EntityNotFoundException e) {
            // expected
        }
    }

    @Override
    protected void assertDeletedColumn(ITypedReferenceableInstance tableInstance) throws AtlasException {
        assertEquals(((List<IReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME)).size(), 2);
    }

    @Override
    protected void assertTestDeleteEntities(ITypedReferenceableInstance tableInstance) {
        int vertexCount = getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, TestUtils.TABLE_TYPE).size();
        assertEquals(vertexCount, 0);

        vertexCount = getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, TestUtils.COLUMN_TYPE).size();
        assertEquals(vertexCount, 0);
    }

    @Override
    protected void assertVerticesDeleted(List<AtlasVertex> vertices) {
        assertEquals(vertices.size(), 0);
    }

    @Override
    protected void assertTestUpdateEntity_MultiplicityOneNonCompositeReference(String janeGuid) throws Exception {
        // Verify that max is no longer a subordinate of jane.
        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(janeGuid);
        List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates");
        Assert.assertEquals(subordinates.size(), 1);
    }

    @Override
    protected void assertJohnForTestDisconnectBidirectionalReferences(ITypedReferenceableInstance john,
                                                                      String janeGuid) throws Exception {
        assertNull(john.get("manager"));
    }

    @Override
    protected void assertMaxForTestDisconnectBidirectionalReferences(Map<String, String> nameGuidMap)
            throws Exception {
        // Verify that the Department.employees reference to the deleted employee
        // was disconnected.
        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(nameGuidMap.get("hr"));
        List<ITypedReferenceableInstance> employees = (List<ITypedReferenceableInstance>) hrDept.get("employees");
        Assert.assertEquals(employees.size(), 3);
        String maxGuid = nameGuidMap.get("Max");
        for (ITypedReferenceableInstance employee : employees) {
            Assert.assertNotEquals(employee.getId()._getId(), maxGuid);
        }

        // Verify that the Manager.subordinates reference to the deleted employee
        // Max was disconnected.
        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(nameGuidMap.get("Jane"));
        List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates");
        assertEquals(subordinates.size(), 1);

        // Verify that max's Person.mentor unidirectional reference to john was disconnected.
        ITypedReferenceableInstance john = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
        assertNull(john.get("mentor"));
    }

    @Override
    protected void assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
            List<ITypedReferenceableInstance> columns, String columnGuid) {
        assertEquals(columns.size(), 4);
        for (ITypedReferenceableInstance column : columns) {
            assertFalse(column.getId()._getId().equals(columnGuid));
        }
    }

    @Override
    protected void assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(String structContainerGuid)
            throws Exception {
        // Verify that the unidirectional references from the struct and trait instances
        // to the deleted entities were disconnected.
        ITypedReferenceableInstance structContainerConvertedEntity =
                repositoryService.getEntityDefinition(structContainerGuid);
        ITypedStruct struct = (ITypedStruct) structContainerConvertedEntity.get("struct");
        assertNull(struct.get("target"));
        IStruct trait = structContainerConvertedEntity.getTrait("TestTrait");
        assertNotNull(trait);
        assertNull(trait.get("target"));
    }

    @Override
    protected void assertTestDisconnectMapReferenceFromClassType(String mapOwnerGuid) throws Exception {
        // Verify map references from mapOwner were disconnected.
        ITypedReferenceableInstance mapOwnerInstance = repositoryService.getEntityDefinition(mapOwnerGuid);
        assertNull(mapOwnerInstance.get("map"));
        assertNull(mapOwnerInstance.get("biMap"));

        AtlasVertex mapOwnerVertex = GraphHelper.getInstance().getVertexForGUID(mapOwnerGuid);
        Object object = mapOwnerVertex.getProperty("MapOwner.map.value1", String.class);
        assertNull(object);
        object = mapOwnerVertex.getProperty("MapOwner.biMap.value1", String.class);
        assertNull(object);
    }

    @Override
    protected void assertTestDeleteTargetOfMultiplicityRequiredReference() throws Exception {

        Assert.fail("Lower bound on attribute Manager.subordinates was not enforced - " +
            NullRequiredAttributeException.class.getSimpleName() + " was expected but none thrown");
    }

    @Override
    protected void assertTestLowerBoundsIgnoredOnDeletedEntities(List<ITypedReferenceableInstance> employees) {

        Assert.assertEquals(employees.size(), 1, "References to deleted employees were not disconnected");
    }

    @Override
    protected void assertTestLowerBoundsIgnoredOnCompositeDeletedEntities(String hrDeptGuid) throws Exception {

        try {
            repositoryService.getEntityDefinition(hrDeptGuid);
            Assert.fail(EntityNotFoundException.class.getSimpleName() + " was expected but none thrown");
        }
        catch (EntityNotFoundException e) {
            // good
        }
    }

    @Override
    protected void verifyTestDeleteEntityWithDuplicateReferenceListElements(List columnsPropertyValue) {

        // With hard deletes enabled, verify that duplicate edge IDs for deleted edges
        // were removed from the array property list.
        Assert.assertEquals(columnsPropertyValue.size(), 2);
    }
}
