/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed 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.onosproject.yangutils.translator.tojava;

import java.util.Objects;

import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangType;
import org.onosproject.yangutils.translator.exception.TranslatorException;
import org.onosproject.yangutils.translator.tojava.utils.AttributesJavaDataType;

import com.google.common.base.MoreObjects;

/**
 * Maintains the information about individual imports in the generated file.
 */
public class JavaQualifiedTypeInfo implements Comparable<JavaQualifiedTypeInfo> {

    /**
     * Package location where the imported class/interface is defined.
     */
    private String pkgInfo;

    /**
     * Class/interface being referenced.
     */
    private String classInfo;

    /**
     * Default constructor.
     */
    public JavaQualifiedTypeInfo() {
    }

    /**
     * Get the imported package info.
     *
     * @return the imported package info
     */
    public String getPkgInfo() {
        return pkgInfo;
    }

    /**
     * Set the imported package info.
     *
     * @param pkgInfo the imported package info
     */
    public void setPkgInfo(String pkgInfo) {
        this.pkgInfo = pkgInfo;
    }

    /**
     * Get the imported class/interface info.
     *
     * @return the imported class/interface info
     */
    public String getClassInfo() {
        return classInfo;
    }

    /**
     * Set the imported class/interface info.
     *
     * @param classInfo the imported class/interface info
     */
    public void setClassInfo(String classInfo) {
        this.classInfo = classInfo;
    }

    /**
     * Get the import info for an attribute, which needs to be used for code
     * generation for import or for qualified access.
     *
     * @param curNode current data model node for which the java file is being
     *            generated.
     * @param attrType type of attribute being added, it will be null, when the
     *            child class is added as an attribute
     * @param attributeName name of the attribute being added, it will used in
     *            import info for child class.
     * @param isListAttr is the added attribute going to be used as a list
     * @return return the import info for this attribute
     */
    public static JavaQualifiedTypeInfo getQualifiedTypeInfoOfLeafAttribute(YangNode curNode,
            YangType<?> attrType, String attributeName,
            boolean isListAttr) {

        JavaQualifiedTypeInfo importInfo = new JavaQualifiedTypeInfo();

        if (attrType == null) {
            throw new TranslatorException("missing data type of leaf " + attributeName);
        }

        /*
         * Current leaves holder is adding a leaf info as a attribute to the
         * current class.
         */
        String className = AttributesJavaDataType.getJavaImportClass(attrType, isListAttr);
        if (className != null) {
            /*
             * Corresponding to the attribute type a class needs to be imported,
             * since it can be a derived type or a usage of wrapper classes.
             */
            importInfo.setClassInfo(className);
            String classPkg = AttributesJavaDataType.getJavaImportPackage(attrType, isListAttr, className);
            if (classPkg == null) {
                throw new TranslatorException("import package cannot be null when the class is used");
            }
            importInfo.setPkgInfo(classPkg);
        } else {
            /*
             * The attribute does not need a class to be imported, for example
             * built in java types.
             */
            String dataTypeName = AttributesJavaDataType.getJavaDataType(attrType);
            if (dataTypeName == null) {
                throw new TranslatorException("not supported data type");
            }
            importInfo.setClassInfo(dataTypeName);
        }
        return importInfo;
    }

    /**
     * Get the import info for an attribute, which needs to be used for code
     * generation for import or for qualified access.
     *
     * @param curNode current data model node for which the java file is being
     *            generated.
     * @param attributeName name of the attribute being added, it will used in
     *            import info for child class.
     * @param isListAttr is the added attribute going to be used as a list
     * @return return the import info for this attribute
     */
    public static JavaQualifiedTypeInfo getQualifiedTypeInfoOfCurNode(YangNode curNode,
            String attributeName, boolean isListAttr) {

        JavaQualifiedTypeInfo importInfo = new JavaQualifiedTypeInfo();

        if (!(curNode instanceof HasJavaFileInfo)) {
            throw new TranslatorException("missing java file information to get the package details "
                    + "of attribute corresponding to child node");
        }
        /*
         * The scenario when we need to add the child class as an attribute in
         * the current class. The child class is in the package of the current
         * classes package with current classes name.
         */
        importInfo.setClassInfo(attributeName);
        importInfo.setPkgInfo((((HasJavaFileInfo) curNode).getJavaFileInfo().getPackage() + "."
                + ((HasJavaFileInfo) curNode).getJavaFileInfo().getJavaName()).toLowerCase());

        return importInfo;
    }

    /**
     * Get if the attribute needs to be accessed in a qualified manner or not,
     * if it needs to be imported, then the same needs to be done.
     *
     * @param curNode current cache of the data model node for which java file
     *            is bing generated
     * @param importInfo import info for the current attribute being added
     * @return status of the qualified access to the attribute
     */
    public static boolean getIsQualifiedAccessOrAddToImportList(YangNode curNode,
            JavaQualifiedTypeInfo importInfo) {

        boolean isImportPkgEqualCurNodePkg;
        if (!(curNode instanceof HasJavaFileInfo)) {
            throw new TranslatorException("missing java file info for getting the qualified access");
        }
        if (importInfo.getClassInfo().contentEquals(
                ((HasJavaFileInfo) curNode).getJavaFileInfo().getJavaName())) {
            /*
             * if the current class name is same as the attribute class name,
             * then the attribute must be accessed in a qualified manner.
             */
            return true;
        } else if (importInfo.getPkgInfo() != null) {
            /*
             * If the attribute type is having the package info, it is contender
             * for import list and also need to check if it needs to be a
             * qualified access.
             */
            isImportPkgEqualCurNodePkg = isImportPkgEqualCurNodePkg(curNode, importInfo);
            if (!isImportPkgEqualCurNodePkg) {
                /*
                 * If the package of the attribute added is not same as the
                 * current class package, then it must either be imported for
                 * access or it must be a qualified access.
                 */
                if (!(curNode instanceof HasJavaImportData)) {
                    /*
                     * If the current data model node is not supposed to import
                     * data, then this is a usage issue and needs to be fixed.
                     */
                    throw new TranslatorException("Current node needs to support Imports");
                }

                boolean isImportAdded = ((HasJavaImportData) curNode).getJavaImportData()
                        .addImportInfo(curNode, importInfo);
                if (!isImportAdded) {
                    /*
                     * If the attribute type info is not imported, then it must
                     * be a qualified access.
                     */
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Check if the import info is same as the package of the current generated
     * java file.
     *
     * @param curNode Java identifier of the current data model node
     * @param importInfo import info for an attribute
     * @return true if the import info is same as the current nodes package
     *         false otherwise
     */
    public static boolean isImportPkgEqualCurNodePkg(
            YangNode curNode, JavaQualifiedTypeInfo importInfo) {

        if (!(curNode instanceof HasJavaFileInfo)) {
            throw new TranslatorException("missing java file info for the data model node");
        }
        return ((HasJavaFileInfo) curNode).getJavaFileInfo().getPackage()
                .contentEquals(importInfo.getPkgInfo()
                        + "." + importInfo.getClassInfo());
    }

    @Override
    public int hashCode() {
        return Objects.hash(pkgInfo, classInfo);
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }
        if (obj instanceof JavaQualifiedTypeInfo) {
            JavaQualifiedTypeInfo other = (JavaQualifiedTypeInfo) obj;
            return Objects.equals(pkgInfo, other.pkgInfo) &&
                    Objects.equals(classInfo, other.classInfo);
        }
        return false;
    }

    /**
     * check if the import info matches.
     *
     * @param importInfo matched import
     * @return if equal or not
     */
    public boolean exactMatch(JavaQualifiedTypeInfo importInfo) {
        return equals(importInfo)
                && Objects.equals(pkgInfo, importInfo.getPkgInfo())
                && Objects.equals(classInfo, importInfo.getClassInfo());
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("pkgInfo", pkgInfo)
                .add("classInfo", classInfo).toString();
    }

    /**
     * Check that there is no 2 objects with the same class name.
     *
     * @param other compared import info.
     */
    @Override
    public int compareTo(JavaQualifiedTypeInfo other) {
        return getClassInfo().compareTo(other.getClassInfo());
    }

}
