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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.UnmodifiableIterator;

import org.apache.atlas.AtlasException;
import org.apache.atlas.typesystem.IStruct;
import org.apache.atlas.typesystem.persistence.DownCastStructInstance;
import org.apache.atlas.typesystem.types.TypeUtils.Pair;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

/**
 * Represents a Type that can have SuperTypes. An Instance of the HierarchicalType can be
 * downcast to a SuperType.
 * @param <ST> the Type of the SuperType. TraitTypes have TraitTypes as SuperTypes, ClassTypes
 *            have ClassTypes
 *            as SuperTypes.
 * @param <T> the class of the Instance of this DataType.
 */
public abstract class HierarchicalType<ST extends HierarchicalType, T> extends AbstractDataType<T> {

    public final TypeSystem typeSystem;
    public final Class<ST> superTypeClass;
    public final FieldMapping fieldMapping;
    public final int numFields;
    public final ImmutableSet<String> superTypes;
    public final ImmutableList<AttributeInfo> immediateAttrs;
    public final ImmutableMap<String, String> attributeNameToType;
    protected ImmutableMap<String, List<Path>> superTypePaths;
    protected ImmutableMap<String, Path> pathNameToPathMap;

    HierarchicalType(TypeSystem typeSystem, Class<ST> superTypeClass, String name, ImmutableSet<String> superTypes,
        int numFields) {
        this(typeSystem, superTypeClass, name, null, superTypes, numFields);
    }

    /**
     * Used when creating a Type, to support recursive Structs.
     */
    HierarchicalType(TypeSystem typeSystem, Class<ST> superTypeClass, String name, String description, ImmutableSet<String> superTypes,
            int numFields) {
        super(name, description);
        this.typeSystem = typeSystem;
        this.superTypeClass = superTypeClass;
        this.fieldMapping = null;
        this.numFields = numFields;
        this.superTypes = superTypes;
        this.immediateAttrs = ImmutableList.of();
        this.attributeNameToType = null;
    }

    HierarchicalType(TypeSystem typeSystem, Class<ST> superTypeClass, String name, ImmutableSet<String> superTypes,
        AttributeInfo... fields) throws AtlasException {
        this(typeSystem, superTypeClass, name, null, superTypes, fields);
    }
    HierarchicalType(TypeSystem typeSystem, Class<ST> superTypeClass, String name, String description, ImmutableSet<String> superTypes,
            AttributeInfo... fields) throws AtlasException {
        super(name, description);
        this.typeSystem = typeSystem;
        this.superTypeClass = superTypeClass;
        Pair<FieldMapping, ImmutableMap<String, String>> p = constructFieldMapping(superTypes, fields);
        this.fieldMapping = p.left;
        this.attributeNameToType = p.right;
        this.numFields = this.fieldMapping.fields.size();
        this.superTypes = superTypes == null ? ImmutableSet.<String>of() : superTypes;
        this.immediateAttrs = ImmutableList.copyOf(fields);
    }

    public FieldMapping fieldMapping() {
        return fieldMapping;
    }

    /**
     * Given type must be a SubType of this type.
     * @param typeName
     * @throws AtlasException
     */
    public boolean isSubType(String typeName) throws AtlasException {
        HierarchicalType cType = typeSystem.getDataType(HierarchicalType.class, typeName);
        return (cType == this || cType.superTypePaths.containsKey(getName()));
    }

    /**
     * Validate that current definition can be updated with the new definition
     * @param newType
     * @return true if the current definition can be updated with the new definition, else false
     */
    @Override
    public void validateUpdate(IDataType newType) throws TypeUpdateException {
        super.validateUpdate(newType);

        HierarchicalType newHierarchicalType = (HierarchicalType) newType;

        //validate on supertypes

        if ((newHierarchicalType.superTypes.size() != superTypes.size())
                || !newHierarchicalType.superTypes.containsAll(superTypes)) {
            throw new TypeUpdateException(newType, "New type cannot modify superTypes");
        }

        //validate on fields
        try {
            TypeUtils.validateUpdate(fieldMapping, newHierarchicalType.fieldMapping);
        } catch (TypeUpdateException e) {
            throw new TypeUpdateException(newType, e);
        }
    }

    protected void setupSuperTypesGraph() throws AtlasException {
        setupSuperTypesGraph(superTypes);
    }

    private void setupSuperTypesGraph(ImmutableSet<String> superTypes) throws AtlasException {
        Map<String, List<Path>> superTypePaths = new HashMap<String, List<Path>>();
        Map<String, Path> pathNameToPathMap = new HashMap<String, Path>();
        Queue<Path> queue = new LinkedList<Path>();
        queue.add(new Node(getName()));
        while (!queue.isEmpty()) {
            Path currentPath = queue.poll();

            ST superType = currentPath.typeName == getName() ? (ST) this :
                    (ST) typeSystem.getDataType(superTypeClass, currentPath.typeName);

            pathNameToPathMap.put(currentPath.pathName, currentPath);
            if (superType != this) {
                List<Path> typePaths = superTypePaths.get(superType.getName());
                if (typePaths == null) {
                    typePaths = new ArrayList<Path>();
                    superTypePaths.put(superType.getName(), typePaths);
                }
                typePaths.add(currentPath);
            }

            ImmutableSet<String> sTs = superType == this ? superTypes : superType.superTypes;

            if (sTs != null) {
                for (String sT : sTs) {
                    queue.add(new Path(sT, currentPath));
                }
            }
        }

        this.superTypePaths = ImmutableMap.copyOf(superTypePaths);
        this.pathNameToPathMap = ImmutableMap.copyOf(pathNameToPathMap);

    }

    protected Pair<FieldMapping, ImmutableMap<String, String>> constructFieldMapping(ImmutableSet<String> superTypes,
            AttributeInfo... fields) throws AtlasException {

        Map<String, AttributeInfo> fieldsMap = new LinkedHashMap();
        Map<String, Integer> fieldPos = new HashMap();
        Map<String, Integer> fieldNullPos = new HashMap();
        Map<String, String> attributeNameToType = new HashMap<>();

        int numBools = 0;
        int numBytes = 0;
        int numShorts = 0;
        int numInts = 0;
        int numLongs = 0;
        int numFloats = 0;
        int numDoubles = 0;
        int numBigInts = 0;
        int numBigDecimals = 0;
        int numDates = 0;
        int numStrings = 0;
        int numArrays = 0;
        int numMaps = 0;
        int numStructs = 0;
        int numReferenceables = 0;

        setupSuperTypesGraph(superTypes);

        Iterator<Path> pathItr = pathIterator();
        while (pathItr.hasNext()) {
            Path currentPath = pathItr.next();

            ST superType = currentPath.typeName == getName() ? (ST) this :
                    (ST) typeSystem.getDataType(superTypeClass, currentPath.typeName);

            ImmutableList<AttributeInfo> superTypeFields =
                    superType == this ? ImmutableList.copyOf(fields) : superType.immediateAttrs;

            Set<String> immediateFields = new HashSet<String>();

            for (AttributeInfo i : superTypeFields) {
                if (superType == this) {
                    if (immediateFields.contains(i.name)) {
                        throw new AtlasException(String.format(
                                "Struct defintion cannot contain multiple fields with the" + " same name %s", i.name));
                    }
                    immediateFields.add(i.name);
                }

                String attrName = i.name;
                if (fieldsMap.containsKey(attrName)) {
                    attrName = currentPath.addOverrideAttr(attrName);
                }
                attributeNameToType.put(attrName, superType.getName());

                fieldsMap.put(attrName, i);
                fieldNullPos.put(attrName, fieldNullPos.size());
                if (i.dataType() == DataTypes.BOOLEAN_TYPE) {
                    fieldPos.put(attrName, numBools);
                    numBools++;
                } else if (i.dataType() == DataTypes.BYTE_TYPE) {
                    fieldPos.put(attrName, numBytes);
                    numBytes++;
                } else if (i.dataType() == DataTypes.SHORT_TYPE) {
                    fieldPos.put(attrName, numShorts);
                    numShorts++;
                } else if (i.dataType() == DataTypes.INT_TYPE) {
                    fieldPos.put(attrName, numInts);
                    numInts++;
                } else if (i.dataType() == DataTypes.LONG_TYPE) {
                    fieldPos.put(attrName, numLongs);
                    numLongs++;
                } else if (i.dataType() == DataTypes.FLOAT_TYPE) {
                    fieldPos.put(attrName, numFloats);
                    numFloats++;
                } else if (i.dataType() == DataTypes.DOUBLE_TYPE) {
                    fieldPos.put(attrName, numDoubles);
                    numDoubles++;
                } else if (i.dataType() == DataTypes.BIGINTEGER_TYPE) {
                    fieldPos.put(attrName, numBigInts);
                    numBigInts++;
                } else if (i.dataType() == DataTypes.BIGDECIMAL_TYPE) {
                    fieldPos.put(attrName, numBigDecimals);
                    numBigDecimals++;
                } else if (i.dataType() == DataTypes.DATE_TYPE) {
                    fieldPos.put(attrName, numDates);
                    numDates++;
                } else if (i.dataType() == DataTypes.STRING_TYPE) {
                    fieldPos.put(attrName, numStrings);
                    numStrings++;
                } else if (i.dataType().getTypeCategory() == DataTypes.TypeCategory.ENUM) {
                    fieldPos.put(i.name, numInts);
                    numInts++;
                } else if (i.dataType().getTypeCategory() == DataTypes.TypeCategory.ARRAY) {
                    fieldPos.put(attrName, numArrays);
                    numArrays++;
                } else if (i.dataType().getTypeCategory() == DataTypes.TypeCategory.MAP) {
                    fieldPos.put(attrName, numMaps);
                    numMaps++;
                } else if (i.dataType().getTypeCategory() == DataTypes.TypeCategory.STRUCT
                        || i.dataType().getTypeCategory() == DataTypes.TypeCategory.TRAIT) {
                    fieldPos.put(attrName, numStructs);
                    numStructs++;
                } else if (i.dataType().getTypeCategory() == DataTypes.TypeCategory.CLASS) {
                    fieldPos.put(attrName, numReferenceables);
                    numReferenceables++;
                } else {
                    throw new AtlasException(String.format("Unknown datatype %s", i.dataType()));
                }
            }
        }

        this.superTypePaths = ImmutableMap.copyOf(superTypePaths);
        this.pathNameToPathMap = ImmutableMap.copyOf(pathNameToPathMap);

        FieldMapping fm =
                new FieldMapping(fieldsMap, fieldPos, fieldNullPos, numBools, numBytes, numShorts, numInts, numLongs,
                        numFloats, numDoubles, numBigInts, numBigDecimals, numDates, numStrings, numArrays, numMaps,
                        numStructs, numReferenceables);

        return new Pair(fm, ImmutableMap.copyOf(attributeNameToType));
    }

    public IStruct castAs(IStruct s, String superTypeName) throws AtlasException {

        if (!superTypePaths.containsKey(superTypeName)) {
            throw new AtlasException(String.format("Cannot downcast to %s from type %s", superTypeName, getName()));
        }

        if (s != null) {
            if (s.getTypeName() != getName()) {
                throw new AtlasException(
                        String.format("Downcast called on wrong type %s, instance type is %s", getName(),
                                s.getTypeName()));
            }

            List<Path> pathToSuper = superTypePaths.get(superTypeName);
            if (pathToSuper.size() > 1) {
                throw new AtlasException(String.format(
                        "Cannot downcast called to %s, from %s: there are multiple paths " + "to SuperType",
                        superTypeName, getName()));
            }

            ST superType = (ST) typeSystem.getDataType(superTypeClass, superTypeName);
            Map<String, String> downCastMap = superType.constructDowncastFieldMap(this, pathToSuper.get(0));
            return new DownCastStructInstance(superTypeName, new DownCastFieldMapping(ImmutableMap.copyOf(downCastMap)),
                    s);
        }

        return null;
    }

    public ST getDefinedType(String attrName) throws AtlasException {
        if (!attributeNameToType.containsKey(attrName)) {
            throw new AtlasException(String.format("Unknown attribute %s in type %s", attrName, getName()));
        }
        return typeSystem.getDataType(superTypeClass, attributeNameToType.get(attrName));
    }

    public String getDefinedTypeName(String attrName) throws AtlasException {
        return getDefinedType(attrName).getName();
    }

    public String getQualifiedName(String attrName) throws AtlasException {
        String attrTypeName = getDefinedTypeName(attrName);
        return attrName.contains(".") ? attrName : String.format("%s.%s", attrTypeName, attrName);
    }

    protected Map<String, String> constructDowncastFieldMap(ST subType, Path pathToSubType) {

        String pathToSubTypeName = pathToSubType.pathAfterThis;
        /*
         * the downcastMap;
         */
        Map<String, String> dCMap = new HashMap<String, String>();
        Iterator<Path> itr = pathIterator();
        while (itr.hasNext()) {
            Path p = itr.next();
            Path pInSubType = (Path) subType.pathNameToPathMap.get(p.pathName + "." + pathToSubTypeName);

            if (pInSubType.hiddenAttributeMap != null) {
                for (Map.Entry<String, String> e : pInSubType.hiddenAttributeMap.entrySet()) {
                    String mappedInThisType =
                            p.hiddenAttributeMap != null ? p.hiddenAttributeMap.get(e.getKey()) : null;
                    if (mappedInThisType == null) {
                        dCMap.put(e.getKey(), e.getValue());
                    } else {
                        dCMap.put(mappedInThisType, e.getValue());
                    }
                }
            }
        }
        return dCMap;
    }

    @Override
    public String toString() {
        StringBuilder buf = new StringBuilder();
        try {
            output(buf, new HashSet<String>());
        }
        catch (AtlasException e) {
            throw new RuntimeException(e);
        }
        return buf.toString();
    }

    @Override
    public void output(Appendable buf, Set<String> typesInProcess) throws AtlasException {

        if (typesInProcess == null) {
            typesInProcess = new HashSet<>();
        }
        else if (typesInProcess.contains(name)) {
            // Avoid infinite recursion on bi-directional reference attributes.
            try {
                buf.append(name);
            } catch (IOException e) {
                throw new AtlasException(e);
            }
            return;
        }

        typesInProcess.add(name);
        try {
            buf.append(getClass().getSimpleName()).append('{');
            buf.append("name=").append(name);
            buf.append(", description=").append(description);
            buf.append(", superTypes=").append(superTypes.toString());
            buf.append(", immediateAttrs=[");
            UnmodifiableIterator<AttributeInfo> it = immediateAttrs.iterator();
            while (it.hasNext()) {
                AttributeInfo attrInfo = it.next();
                attrInfo.output(buf, typesInProcess);
                if (it.hasNext()) {
                    buf.append(", ");
                }
                else {
                    buf.append(']');
                }
            }
            buf.append("}");
        }
        catch(IOException e) {
            throw new AtlasException(e);
        }
        finally {
            typesInProcess.remove(name);
        }
    }

    public Set<String> getAllSuperTypeNames() {
        return superTypePaths.keySet();
    }

    public Iterator<Path> pathIterator() {
        return new PathItr();
    }

    static class Path {
        public final String typeName;
        public final String pathName;
        public final String pathAfterThis;
        private final Path subTypePath;
        /*
         * name mapping for attributes hidden by a SubType.
         */ Map<String, String> hiddenAttributeMap;

        Path(String typeName, Path childPath) throws AtlasException {
            this.typeName = typeName;
            this.subTypePath = childPath;
            if (childPath.contains(typeName)) {
                throw new CyclicTypeDefinition(this);
            }
            pathName = String.format("%s.%s", typeName, childPath.pathName);
            pathAfterThis = childPath.pathName;
        }

        Path(String typeName) {
            assert getClass() == Node.class;
            this.typeName = typeName;
            this.subTypePath = null;
            pathName = typeName;
            pathAfterThis = null;
        }

        public boolean contains(String typeName) {
            return this.typeName.equals(typeName) || (subTypePath != null && subTypePath.contains(typeName));
        }

        public String pathString(String nodeSep) {

            StringBuilder b = new StringBuilder();
            Path p = this;

            while (p != null) {
                b.append(p.typeName);
                p = p.subTypePath;
                if (p != null) {
                    b.append(nodeSep);
                }
            }
            return b.toString();
        }

        String addOverrideAttr(String name) {
            hiddenAttributeMap = hiddenAttributeMap == null ? new HashMap<String, String>() : hiddenAttributeMap;
            String oName = pathName + "." + name;
            hiddenAttributeMap.put(name, oName);
            return oName;
        }
    }

    static class Node extends Path {
        Node(String typeName) {
            super(typeName);
        }
    }

    static class CyclicTypeDefinition extends AtlasException {

        CyclicTypeDefinition(Path p) {
            super(String.format("Cycle in Type Definition %s", p.pathString(" -> ")));
        }
    }

    class PathItr implements Iterator<Path> {

        Queue<Path> pathQueue;

        PathItr() {
            pathQueue = new LinkedList<Path>();
            pathQueue.add(pathNameToPathMap.get(getName()));
        }

        @Override
        public boolean hasNext() {
            return !pathQueue.isEmpty();
        }

        @Override
        public Path next() {
            Path p = pathQueue.poll();

            if(p != null) {
                ST t = null;
                try {
                    t = (ST) typeSystem.getDataType(superTypeClass, p.typeName);
                } catch (AtlasException me) {
                    throw new RuntimeException(me);
                }
                if (t.superTypes != null) {
                    ImmutableSet<String> sTs = t.superTypes;
                    for (String sT : sTs) {
                        String nm = sT + "." + p.pathName;
                        pathQueue.add(pathNameToPathMap.get(nm));
                    }
                }
            }
            return p;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }
}
