/*  Copyright 2008 Edward Yakop.
*
* 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.apache.zest.ide.plugin.idea.mixins.inspections;

import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import org.jetbrains.annotations.NotNull;
import org.apache.zest.ide.plugin.idea.common.inspections.AbstractFix;
import org.apache.zest.ide.plugin.idea.common.inspections.AbstractInspection;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
import static org.apache.zest.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
import static org.apache.zest.ide.plugin.idea.concerns.common.Qi4jConcernUtil.isAConcern;
import static org.apache.zest.ide.plugin.idea.mixins.common.Qi4jMixinUtil.*;
import static org.apache.zest.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil.isASideEffect;

/**
 * @author edward.yakop@gmail.com
 * @since 0.1
 */
public final class MixinImplementsMixinType extends AbstractInspection
{
    @NotNull
    protected final String resourceBundlePrefixId()
    {
        return "mixin.implements.mixin.type";
    }

    @NotNull
    public final String getShortName()
    {
        return "MixinImplementsMixinType";
    }

    @Override
    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
                                                 @NotNull InspectionManager manager,
                                                 boolean isOnTheFly )
    {
        // If psiClass is not an interface, ignore
        if( !psiClass.isInterface() )
        {
            return null;
        }

        // If @Mixins annotation is empty, ignore
        List<PsiAnnotationMemberValue> mixinAnnotationValues = getMixinsAnnotationValue( psiClass );
        if( mixinAnnotationValues.isEmpty() )
        {
            return null;
        }

        // Get all valid mixin type
        Set<PsiClass> validMixinsType = getAllValidMixinTypes( psiClass );
        if( validMixinsType.isEmpty() )
        {
            return null;
        }

        // For each mixin
        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
        for( PsiAnnotationMemberValue mixinAnnotationValue : mixinAnnotationValues )
        {
            PsiJavaCodeReferenceElement mixinClassReference = getMixinClassReference( mixinAnnotationValue );

            // If it's not a class reference, ignore
            if( mixinClassReference == null )
            {
                continue;
            }

            // If class reference can't be resolved, ignore
            PsiClass mixinClass = (PsiClass) mixinClassReference.resolve();
            if( mixinClass == null )
            {
                continue;
            }

            String mixinQualifiedName = mixinClass.getQualifiedName();

            boolean isMixinsDeclarationValid = false;
            String message = "";
            if( mixinClass.isInterface() )
            {
                // Mixin can't be an interface
                message = message( "mixin.implements.mixin.type.error.mixin.is.an.interface", mixinQualifiedName );
            }
            else if( isAConcern( mixinClass ) )
            {
                // Mixin can't be a concern
                message = message( "mixin.implements.mixin.type.error.mixin.is.a.concern", mixinQualifiedName );
            }
            else if( isASideEffect( mixinClass ) )
            {
                // Mixin can't be a side effect
                message = message( "mixin.implements.mixin.type.error.mixin.is.a.side.effect", mixinQualifiedName );
            }
            else
            {
                // If doesn't implement any mixin type, it's a problem
                if( !isImplementValidMixinType( mixinClass, validMixinsType ) )
                {
                    message = message(
                        "mixin.implements.mixin.type.error.does.not.implement.any.mixin.type",
                        mixinQualifiedName,
                        psiClass.getQualifiedName()
                    );
                }
                else
                {
                    isMixinsDeclarationValid = true;
                }
            }

            if( !isMixinsDeclarationValid )
            {
                ProblemDescriptor problemDescriptor = createProblemDescriptor(
                    manager, mixinAnnotationValue, mixinClassReference, message );
                problems.add( problemDescriptor );
            }
        }

        return problems.toArray( new ProblemDescriptor[problems.size()] );
    }

    private boolean isImplementValidMixinType( PsiClass mixinClass, Set<PsiClass> validMixinsType )
    {
        for( PsiClass validMixinTypeClass : validMixinsType )
        {
            if( mixinClass.isInheritor( validMixinTypeClass, true ) )
            {
                return true;
            }
        }

        return false;
    }

    private ProblemDescriptor createProblemDescriptor( @NotNull InspectionManager manager,
                                                       @NotNull PsiAnnotationMemberValue mixinAnnotationValue,
                                                       @NotNull PsiJavaCodeReferenceElement mixinClassReference,
                                                       @NotNull String message )
    {
        RemoveInvalidMixinClassReferenceFix fix = new RemoveInvalidMixinClassReferenceFix(
            mixinAnnotationValue, mixinClassReference
        );
        return manager.createProblemDescriptor( mixinAnnotationValue, message, fix, GENERIC_ERROR_OR_WARNING );
    }

    private static class RemoveInvalidMixinClassReferenceFix extends AbstractFix
    {
        private final PsiAnnotationMemberValue mixinClassAnnotationValue;

        public RemoveInvalidMixinClassReferenceFix( @NotNull PsiAnnotationMemberValue mixinClassAnnotationValue,
                                                    @NotNull PsiJavaCodeReferenceElement mixinClassReference )
        {
            super( message( "mixin.implements.mixin.type.fix.remove.class.reference", mixinClassReference.getQualifiedName() ) );
            this.mixinClassAnnotationValue = mixinClassAnnotationValue;
        }

        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
        {
            mixinClassAnnotationValue.delete();
        }
    }
}
