/*
 * 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.netbeans.modules.j2ee.ejbverification;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.netbeans.api.java.source.CompilationInfo;

/**
 *
 * @author Tomasz.Slota
 */
public class JavaUtils {
    public static String extractClassNameFromType(TypeMirror type){
        if (type instanceof DeclaredType){
            Element elem = ((DeclaredType)type).asElement();
            
            if (elem.getKind() == ElementKind.CLASS
                    || elem.getKind() == ElementKind.INTERFACE){
                return ((TypeElement)elem).getQualifiedName().toString();
            }
        }
        
        return null;
    }
    
    /**
     * A convenience method, returns true if findAnnotation(...) != null
     */
    public static boolean hasAnnotation(Element element, String annClass){
        AnnotationMirror annEntity = findAnnotation(element, annClass);
        return annEntity != null;
    }
    
    public static AnnotationMirror findAnnotation(Element element, String annotationClass){
        for (AnnotationMirror ann : element.getAnnotationMirrors()){
            if (annotationClass.equals(ann.getAnnotationType().toString())){
                return ann;
            }
        }
        
        return null;
    }
    
    /**
     * @return the value of annotation attribute, null if the attribute
     * was not found or when ann was null
     */
    public static AnnotationValue getAnnotationAttrValue(AnnotationMirror ann, String attrName){
        if (ann != null){
            for (ExecutableElement attr : ann.getElementValues().keySet()){
                if (attrName.equals(attr.getSimpleName().toString())){
                    return ann.getElementValues().get(attr);
                }
            }
        }
        
        return null;
    }
    
    public static String getShortClassName(String qualifiedClassName){
        return qualifiedClassName.substring(qualifiedClassName.lastIndexOf(".") + 1); //NOI18N
    }

    public static boolean isMethodSignatureSame(CompilationInfo cinfo,
            ExecutableElement method1, ExecutableElement method2){

        // check for parameters count
        int paramCount = method1.getParameters().size();
        if (paramCount != method2.getParameters().size()) {
            return false;
        }

        for (int i = 0; i < paramCount; i++) {
            TypeMirror param1 = method1.getParameters().get(i).asType();
            TypeMirror param2 = method2.getParameters().get(i).asType();

            if (!cinfo.getTypes().isSameType(param1, param2)) {
                if (isSameDeclaredType(param1, param2)) {
                    continue;
                } else if (param2.getKind() == TypeKind.TYPEVAR) {
                    // interface method contains type erasure - see issue #201543
                    if (isParamEquivalentOfErasure(cinfo, method1, method2, param1.toString(), param2.toString())) {
                        continue;
                    }
                }
                return false;
            }
        }
        return true;
    }

    private static boolean isParamEquivalentOfErasure(CompilationInfo cinfo, ExecutableElement sourceMethod,
            ExecutableElement targetMethod, String sourceParam, String targetParam) {
        TypeMirror classTypeMirror = sourceMethod.getEnclosingElement().asType();
        for (TypeMirror typeMirror : cinfo.getTypes().directSupertypes(classTypeMirror)) {
            if (typeMirror instanceof DeclaredType) {
                DeclaredType declaredType = (DeclaredType) typeMirror;
                if (declaredType.asElement().getEnclosedElements().contains(targetMethod)) {
                    HashMap<String, String> argumentNamesMap = getErasureTypesMap(
                            cinfo.getElementUtilities().enclosingTypeElement(targetMethod).getTypeParameters(),
                            declaredType.getTypeArguments());

                    if (sourceParam.equals(argumentNamesMap.get(targetParam))) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private static HashMap<String, String> getErasureTypesMap(List<? extends TypeParameterElement> erasureArguments,
            List<? extends TypeMirror> typeArguments) {
        HashMap<String, String> result = new HashMap<String, String>(erasureArguments.size());

        for (int i = 0; i < erasureArguments.size(); i++) {
            if (erasureArguments.size() == i || typeArguments.size() == i) {
                return result;
            }
            result.put(erasureArguments.get(i).toString(), typeArguments.get(i).toString());
        }
        return result;
    }

    public static boolean isSameDeclaredType(TypeMirror param1, TypeMirror param2) {
        String classNameParam1 = extractClassNameFromType(param1);
        // classNameParam1 == null when param1 is not declared type
        if (classNameParam1 != null && classNameParam1.equals(extractClassNameFromType(param2))) {
            return true;
        }
        return false;
    }

    /**
     * Says whether given element is subtype of the entered type.
     * @param info compilation info
     * @param element element to be examined
     * @param superType type which is looking for
     * @return {@code true} is the element implements or extends the given superType, {@code false} otherwise
     */
    public static boolean isTypeOf(CompilationInfo info, Element element, String superType) {
        final TypeMirror tm = element.asType();
        List<Element> types = new ArrayList<>();

        Deque<TypeMirror> deque = new ArrayDeque<>();
        deque.add(tm);
        while (!deque.isEmpty()) {
            TypeMirror mirror = deque.pop();
            if (mirror.getKind() == TypeKind.DECLARED) {
                Element el = info.getTypes().asElement(mirror);
                types.add(el);
                if (el.getKind() == ElementKind.CLASS) {
                    TypeElement tel = (TypeElement) el;
                    deque.add(tel.getSuperclass());
                    deque.addAll(tel.getInterfaces());
                } else if (el.getKind() == ElementKind.INTERFACE) {
                    TypeElement tel = (TypeElement) el;
                    for (TypeMirror ifaceMirror : tel.getInterfaces()) {
                        deque.add(ifaceMirror);
                    }
                }
            }
        }

        for (Element type : types) {
            if (superType.equals(type.asType().toString())) {
                return true;
            }
        }
        return false;
    }
}
