/**
 * 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 com.tinkerpop.blueprints.Vertex;
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.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.persistence.Id;
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.apache.atlas.TestUtils.NAME;
import static org.apache.atlas.TestUtils.PII;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

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

    @Override
    protected void assertTestDeleteEntityWithTraits(String guid) throws Exception {
        ITypedReferenceableInstance instance = repositoryService.getEntityDefinition(guid);
        assertTrue(instance.getTraits().contains(PII));
    }

    @Override
    protected void assertTableForTestDeleteReference(String tableId) throws Exception  {
        ITypedReferenceableInstance table = repositoryService.getEntityDefinition(tableId);
        assertNotNull(table.get(NAME));
        assertNotNull(table.get("description"));
        assertNotNull(table.get("type"));
        assertNotNull(table.get("tableType"));
        assertNotNull(table.get("created"));

        Id dbId = (Id) table.get("database");
        assertNotNull(dbId);

        ITypedReferenceableInstance db = repositoryService.getEntityDefinition(dbId.getId()._getId());
        assertNotNull(db);
        assertEquals(db.getId().getState(), Id.EntityState.ACTIVE);
    }

    @Override
    protected void assertColumnForTestDeleteReference(ITypedReferenceableInstance tableInstance) throws AtlasException {
        List<ITypedReferenceableInstance> columns =
                (List<ITypedReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
        assertEquals(columns.size(), 1);
        assertEquals(columns.get(0).getId().getState(), Id.EntityState.DELETED);
    }

    @Override
    protected void assertProcessForTestDeleteReference(ITypedReferenceableInstance expected) throws Exception {
        ITypedReferenceableInstance process = repositoryService.getEntityDefinition(expected.getId()._getId());
        List<ITypedReferenceableInstance> outputs =
                (List<ITypedReferenceableInstance>) process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS);
        List<ITypedReferenceableInstance> expectedOutputs =
                (List<ITypedReferenceableInstance>) process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS);
        assertEquals(outputs.size(), expectedOutputs.size());
    }

    @Override
    protected void assertEntityDeleted(String id) throws Exception {
        ITypedReferenceableInstance entity = repositoryService.getEntityDefinition(id);
        assertEquals(entity.getId().getState(), Id.EntityState.DELETED);
    }

    @Override
    protected void assertDeletedColumn(ITypedReferenceableInstance tableInstance) throws AtlasException {
        List<IReferenceableInstance> columns = (List<IReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
        assertEquals(columns.size(), 3);
        assertEquals(columns.get(0).getId().getState(), Id.EntityState.DELETED);
    }

    @Override
    protected void assertTestDeleteEntities(ITypedReferenceableInstance expected) throws Exception {
        //Assert that the deleted table can be fully constructed back
        ITypedReferenceableInstance table = repositoryService.getEntityDefinition(expected.getId()._getId());
        List<ITypedReferenceableInstance> columns =
                (List<ITypedReferenceableInstance>) table.get(TestUtils.COLUMNS_ATTR_NAME);
        List<ITypedReferenceableInstance> expectedColumns =
                (List<ITypedReferenceableInstance>) table.get(TestUtils.COLUMNS_ATTR_NAME);
        assertEquals(columns.size(), expectedColumns.size());
        assertNotNull(table.get("database"));
    }

    @Override
    protected void assertVerticesDeleted(List<Vertex> vertices) {
        for (Vertex vertex : vertices) {
            assertEquals(vertex.getProperty(Constants.STATE_PROPERTY_KEY), Id.EntityState.DELETED.name());
        }
    }

    @Override
    protected void assertTestUpdateEntity_MultiplicityOneNonCompositeReference(String janeGuid) throws Exception {
        // Verify Jane's subordinates reference cardinality is still 2.
        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(janeGuid);
        List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates");
        Assert.assertEquals(subordinates.size(), 2);
    }

    @Override
    protected void assertJohnForTestDisconnectBidirectionalReferences(ITypedReferenceableInstance john, String janeGuid)
            throws Exception {
        Id mgr = (Id) john.get("manager");
        assertNotNull(mgr);
        assertEquals(mgr._getId(), janeGuid);
        assertEquals(mgr.getState(), Id.EntityState.DELETED);
    }

    @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(), 4);
        String maxGuid = nameGuidMap.get("Max");
        for (ITypedReferenceableInstance employee : employees) {
            if (employee.getId()._getId().equals(maxGuid)) {
                assertEquals(employee.getId().getState(), Id.EntityState.DELETED);
            }
        }

        // Verify that the Manager.subordinates still references deleted employee
        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(nameGuidMap.get("Jane"));
        List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates");
        assertEquals(subordinates.size(), 2);
        for (ITypedReferenceableInstance subordinate : subordinates) {
            if (subordinate.getId()._getId().equals(maxGuid)) {
                assertEquals(subordinate.getId().getState(), Id.EntityState.DELETED);
            }
        }

        // Verify that max's Person.mentor unidirectional reference to john was disconnected.
        ITypedReferenceableInstance john = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
        Id mentor = (Id) john.get("mentor");
        assertEquals(mentor._getId(), maxGuid);
        assertEquals(mentor.getState(), Id.EntityState.DELETED);
    }

    @Override
    protected void assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
            List<ITypedReferenceableInstance> columns, String columnGuid) {
        Assert.assertEquals(columns.size(), 5);
        for (ITypedReferenceableInstance column : columns) {
            if (column.getId()._getId().equals(columnGuid)) {
                assertEquals(column.getId().getState(), Id.EntityState.DELETED);
            } else {
                assertEquals(column.getId().getState(), Id.EntityState.ACTIVE);
            }
        }

    }

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

    }

    @Override
    protected void assertTestDisconnectMapReferenceFromClassType(String mapOwnerGuid) throws Exception {
        ITypedReferenceableInstance mapOwnerInstance = repositoryService.getEntityDefinition(mapOwnerGuid);
        Map<String, ITypedReferenceableInstance> map =
                (Map<String, ITypedReferenceableInstance>) mapOwnerInstance.get("map");
        assertNotNull(map);
        assertEquals(map.size(), 1);
        Map<String, ITypedReferenceableInstance> biMap =
                (Map<String, ITypedReferenceableInstance>) mapOwnerInstance.get("biMap");
        assertNotNull(biMap);
        assertEquals(biMap.size(), 1);
    }

    @Override
    protected void assertTestDeleteTargetOfMultiplicityRequiredReference() throws Exception {
        // No-op - it's ok that no exception was thrown if soft deletes are enabled.
    }
}
