/**
 * 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.type;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.ModelTestUtil;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry;
import org.testng.annotations.Test;

import static org.testng.Assert.*;


public class TestAtlasEntityType {
    private static final String TYPE_TABLE   = "my_table";
    private static final String TYPE_COLUMN  = "my_column";
    private static final String ATTR_TABLE   = "table";
    private static final String ATTR_COLUMNS = "columns";
    private static final String ATTR_NAME    = "name";

    private final AtlasEntityType entityType;
    private final List<Object>    validValues   = new ArrayList<>();
    private final List<Object>    invalidValues = new ArrayList<>();

    {
        entityType  = getEntityType(ModelTestUtil.getEntityDefWithSuperTypes());

        AtlasEntity         invalidValue1 = entityType.createDefaultValue();
        AtlasEntity         invalidValue2 = entityType.createDefaultValue();
        Map<String, Object> invalidValue3 = entityType.createDefaultValue().getAttributes();

        // invalid value for int
        invalidValue1.setAttribute(ModelTestUtil.getDefaultAttributeName(AtlasBaseTypeDef.ATLAS_TYPE_INT), "xyz");
        // invalid value for date
        invalidValue2.setAttribute(ModelTestUtil.getDefaultAttributeName(AtlasBaseTypeDef.ATLAS_TYPE_DATE), "xyz");
        // invalid value for bigint
        invalidValue3.put(ModelTestUtil.getDefaultAttributeName(AtlasBaseTypeDef.ATLAS_TYPE_BIGINTEGER), "xyz");

        validValues.add(null);
        validValues.add(entityType.createDefaultValue());
        validValues.add(entityType.createDefaultValue().getAttributes()); // Map<String, Object>
        invalidValues.add(invalidValue1);
        invalidValues.add(invalidValue2);
        invalidValues.add(invalidValue3);
        invalidValues.add(new AtlasEntity());             // no values for mandatory attributes
        invalidValues.add(new HashMap<>()); // no values for mandatory attributes
        invalidValues.add(1);               // incorrect datatype
        invalidValues.add(new HashSet());   // incorrect datatype
        invalidValues.add(new ArrayList()); // incorrect datatype
        invalidValues.add(new String[] {}); // incorrect datatype
    }

    @Test
    public void testEntityTypeDefaultValue() {
        AtlasEntity defValue = entityType.createDefaultValue();

        assertNotNull(defValue);
        assertEquals(defValue.getTypeName(), entityType.getTypeName());
    }

    @Test
    public void testEntityTypeIsValidValue() {
        for (Object value : validValues) {
            assertTrue(entityType.isValidValue(value), "value=" + value);
        }

        for (Object value : invalidValues) {
            assertFalse(entityType.isValidValue(value), "value=" + value);
        }
    }

    @Test
    public void testEntityTypeGetNormalizedValue() {
        assertNull(entityType.getNormalizedValue(null), "value=" + null);

        for (Object value : validValues) {
            if (value == null) {
                continue;
            }

            Object normalizedValue = entityType.getNormalizedValue(value);

            assertNotNull(normalizedValue, "value=" + value);
        }

        for (Object value : invalidValues) {
            assertNull(entityType.getNormalizedValue(value), "value=" + value);
        }
    }

    @Test
    public void testEntityTypeValidateValue() {
        List<String> messages = new ArrayList<>();
        for (Object value : validValues) {
            assertTrue(entityType.validateValue(value, "testObj", messages));
            assertEquals(messages.size(), 0, "value=" + value);
        }

        for (Object value : invalidValues) {
            assertFalse(entityType.validateValue(value, "testObj", messages));
            assertTrue(messages.size() > 0, "value=" + value);
            messages.clear();
        }
    }

    @Test
    public void testValidConstraints() {
        AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
        AtlasTransientTypeRegistry ttr          = null;
        boolean                    commit       = false;
        List<AtlasEntityDef>       entityDefs   = new ArrayList<>();
        String                     failureMsg   = null;

        entityDefs.add(createTableEntityDef());
        entityDefs.add(createColumnEntityDef());

        try {
            ttr = typeRegistry.lockTypeRegistryForUpdate();

            ttr.addTypes(entityDefs);

            AtlasEntityType typeTable  = ttr.getEntityTypeByName(TYPE_TABLE);
            AtlasEntityType typeColumn = ttr.getEntityTypeByName(TYPE_COLUMN);

            assertTrue(typeTable.getAttribute(ATTR_COLUMNS).isOwnedRef());
            assertNull(typeTable.getAttribute(ATTR_COLUMNS).getInverseRefAttributeName());
            assertFalse(typeColumn.getAttribute(ATTR_TABLE).isOwnedRef());
            assertEquals(typeColumn.getAttribute(ATTR_TABLE).getInverseRefAttributeName(), ATTR_COLUMNS);
            assertEquals(typeColumn.getAttribute(ATTR_TABLE).getInverseRefAttribute(), typeTable.getAttribute(ATTR_COLUMNS));

            commit = true;
        } catch (AtlasBaseException excp) {
            failureMsg = excp.getMessage();
        } finally {
            typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
        }
        assertNull(failureMsg, "failed to create types " + TYPE_TABLE + " and " + TYPE_COLUMN);
    }

    @Test
    public void testConstraintInvalidOwnedRef_InvalidAttributeType() {
        AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
        AtlasTransientTypeRegistry ttr          = null;
        boolean                    commit       = false;
        List<AtlasEntityDef>       entityDefs   = new ArrayList<>();
        AtlasErrorCode             errorCode   = null;

        entityDefs.add(createTableEntityDefWithOwnedRefOnInvalidType());

        try {
            ttr = typeRegistry.lockTypeRegistryForUpdate();

            ttr.addTypes(entityDefs);

            commit = true;
        } catch (AtlasBaseException excp) {
            errorCode = excp.getAtlasErrorCode();
        } finally {
            typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
        }
        assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_OWNED_REF_ATTRIBUTE_INVALID_TYPE,
                "expected invalid constraint failure - missing refAttribute");
    }

    @Test
    public void testConstraintInValidInverseRef_MissingParams() {
        AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
        AtlasTransientTypeRegistry ttr          = null;
        boolean                    commit       = false;
        List<AtlasEntityDef>       entityDefs   = new ArrayList<>();
        AtlasErrorCode             errorCode   = null;

        entityDefs.add(createTableEntityDef());
        entityDefs.add(createColumnEntityDefWithMissingInverseAttribute());

        try {
            ttr = typeRegistry.lockTypeRegistryForUpdate();

            ttr.addTypes(entityDefs);

            commit = true;
        } catch (AtlasBaseException excp) {
            errorCode = excp.getAtlasErrorCode();
        } finally {
            typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
        }
        assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_MISSING_PARAMS,
                "expected invalid constraint failure - missing refAttribute");
    }

    @Test
    public void testConstraintInValidInverseRef_InvalidAttributeTypeForInverseAttribute() {
        AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
        AtlasTransientTypeRegistry ttr          = null;
        boolean                    commit       = false;
        List<AtlasEntityDef>       entityDefs   = new ArrayList<>();
        AtlasErrorCode             errorCode   = null;

        entityDefs.add(createTableEntityDef());
        entityDefs.add(createColumnEntityDefWithInvaidAttributeTypeForInverseAttribute());

        try {
            ttr = typeRegistry.lockTypeRegistryForUpdate();

            ttr.addTypes(entityDefs);

            commit = true;
        } catch (AtlasBaseException excp) {
            errorCode = excp.getAtlasErrorCode();
        } finally {
            typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
        }
        assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_ATTRIBUTE_INVALID_TYPE,
                "expected invalid constraint failure - missing refAttribute");
    }

    @Test
    public void testConstraintInValidInverseRef_InvalidAttributeType() {
        AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
        AtlasTransientTypeRegistry ttr          = null;
        boolean                    commit       = false;
        List<AtlasEntityDef>       entityDefs   = new ArrayList<>();
        AtlasErrorCode             errorCode   = null;

        entityDefs.add(createTableEntityDef());
        entityDefs.add(createColumnEntityDefWithInvalidInverseAttributeType());

        try {
            ttr = typeRegistry.lockTypeRegistryForUpdate();

            ttr.addTypes(entityDefs);

            commit = true;
        } catch (AtlasBaseException excp) {
            errorCode = excp.getAtlasErrorCode();
        } finally {
            typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
        }
        assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_INVALID_TYPE,
                "expected invalid constraint failure - invalid refAttribute type");
    }

    @Test
    public void testConstraintInValidInverseRef_NonExistingAttribute() {
        AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
        AtlasTransientTypeRegistry ttr          = null;
        boolean                    commit       = false;
        List<AtlasEntityDef>       entityDefs   = new ArrayList<>();
        AtlasErrorCode             errorCode   = null;

        entityDefs.add(createTableEntityDef());
        entityDefs.add(createColumnEntityDefWithNonExistingInverseAttribute());

        try {
            ttr = typeRegistry.lockTypeRegistryForUpdate();

            ttr.addTypes(entityDefs);

            commit = true;
        } catch (AtlasBaseException excp) {
            errorCode = excp.getAtlasErrorCode();
        } finally {
            typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
        }
        assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_NON_EXISTING,
                     "expected invalid constraint failure - non-existing refAttribute");
    }

    private static AtlasEntityType getEntityType(AtlasEntityDef entityDef) {
        try {
            return new AtlasEntityType(entityDef, ModelTestUtil.getTypesRegistry());
        } catch (AtlasBaseException excp) {
            return null;
        }
    }

    private AtlasEntityDef createTableEntityDef() {
        AtlasEntityDef    table       = new AtlasEntityDef(TYPE_TABLE);
        AtlasAttributeDef attrName    = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
        AtlasAttributeDef attrColumns = new AtlasAttributeDef(ATTR_COLUMNS,
                                                              AtlasBaseTypeDef.getArrayTypeName(TYPE_COLUMN));

        attrColumns.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));

        table.addAttribute(attrName);
        table.addAttribute(attrColumns);

        return table;
    }

    private AtlasEntityDef createTableEntityDefWithOwnedRefOnInvalidType() {
        AtlasEntityDef    table    = new AtlasEntityDef(TYPE_TABLE);
        AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);

        attrName.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));

        table.addAttribute(attrName);

        return table;
    }

    private AtlasEntityDef createColumnEntityDefWithMissingInverseAttribute() {
        AtlasEntityDef    column    = new AtlasEntityDef(TYPE_COLUMN);
        AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);

        attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF));
        column.addAttribute(attrTable);

        return column;
    }

    private AtlasEntityDef createColumnEntityDefWithInvaidAttributeTypeForInverseAttribute() {
        AtlasEntityDef    column    = new AtlasEntityDef(TYPE_COLUMN);
        AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);

        Map<String, Object> params = new HashMap<>();
        params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_NAME);

        attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
        column.addAttribute(attrTable);

        return column;
    }

    private AtlasEntityDef createColumnEntityDefWithNonExistingInverseAttribute() {
        AtlasEntityDef    column    = new AtlasEntityDef(TYPE_COLUMN);
        AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);

        Map<String, Object> params = new HashMap<>();
        params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, "non-existing:" + ATTR_COLUMNS);

        attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
        column.addAttribute(attrTable);

        return column;
    }

    private AtlasEntityDef createColumnEntityDefWithInvalidInverseAttributeType() {
        AtlasEntityDef    column    = new AtlasEntityDef(TYPE_COLUMN);
        AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);

        Map<String, Object> params = new HashMap<>();
        params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_NAME);

        attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
        column.addAttribute(attrTable);

        return column;
    }

    private AtlasEntityDef createColumnEntityDef() {
        AtlasEntityDef    column    = new AtlasEntityDef(TYPE_COLUMN);
        AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);

        Map<String, Object> params = new HashMap<>();
        params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_COLUMNS);

        attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
        column.addAttribute(attrTable);

        return column;
    }
}
