/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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.jetbrains.idea.devkit.references;

import com.intellij.find.FindModel;
import com.intellij.find.impl.FindInProjectUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.patterns.*;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceUtil;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiFileReference;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.FindUsagesProcessPresentation;
import com.intellij.usages.UsageViewPresentation;
import com.intellij.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.util.PsiUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.intellij.patterns.PsiJavaPatterns.*;

/**
 * @author Konstantin Bulenkov
 */
public class IconsReferencesContributor extends PsiReferenceContributor implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
  @Override
  public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
    final StringPattern methodName = string().oneOf("findIcon", "getIcon");
    final PsiMethodPattern method = psiMethod().withName(methodName).definedInClass(IconLoader.class.getName());
    final PsiJavaElementPattern.Capture<PsiLiteralExpression> javaFile
      = literalExpression().and(psiExpression().methodCallParameter(0, method));

    final PsiJavaElementPattern.Capture<PsiLiteralExpression> annotationValue
      = literalExpression().annotationParam("com.intellij.ide.presentation.Presentation", "icon");

    final XmlAttributeValuePattern pluginXml = XmlPatterns.xmlAttributeValue().withLocalName("icon");

    registrar.registerReferenceProvider(annotationValue, new PsiReferenceProvider() {
      @NotNull
      @Override
      public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
        if (!PsiUtil.isIdeaProject(element.getProject())) return PsiReference.EMPTY_ARRAY;
        return new PsiReference[] {
          new PsiReferenceBase<PsiElement>(element, true) {
            @Override
            public PsiElement resolve() {
              String value = (String)((PsiLiteralExpression)element).getValue();
              if (value != null) {
                List<String> path = StringUtil.split(value, ".");
                if (path.size() > 1 && path.get(0).endsWith("Icons")) {
                  Project project = element.getProject();
                  PsiClass cur = JavaPsiFacade.getInstance(project).findClass(fqnIconsClass(path.get(0)),
                                                                              GlobalSearchScope.projectScope(project));
                  if (cur == null) {
                    return null;
                  }

                  for (int i = 1; i < path.size() - 1; i++) {
                    cur = cur.findInnerClassByName(path.get(i), false);
                    if (cur == null) {
                      return null;
                    }
                  }

                  return cur.findFieldByName(path.get(path.size() - 1), false);
                }
              }

              return null;
            }

            @Override
            public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
              PsiElement field = resolve();
              if (field instanceof PsiField) {
                String fqn = ((PsiField)field).getContainingClass().getQualifiedName();

                if (fqn.startsWith("com.intellij.icons.")) {
                  return replace(newElementName, fqn, "com.intellij.icons.", element);
                }
                else if (fqn.startsWith("icons.")) {
                  return replace(newElementName, fqn, "icons.", element);
                }
              }

              return super.handleElementRename(newElementName);
            }

            @Override
            public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
              if (element instanceof PsiField) {
                String fqn = ((PsiField)element).getContainingClass().getQualifiedName();

                String newElementName = ((PsiField)element).getName();
                if (fqn.startsWith("com.intellij.icons.")) {
                  return replace(newElementName, fqn, "com.intellij.icons.", getElement());
                }
                else if (fqn.startsWith("icons.")) {
                  return replace(newElementName, fqn, "icons.", getElement());
                }
              }

              return super.bindToElement(element);
            }

            private PsiElement replace(String newElementName, String fqn, String pckg, PsiElement container) {
              String newValue = "\"" + fqn.substring(pckg.length()) + "." + newElementName + "\"";
              return getElement().replace(
                JavaPsiFacade.getElementFactory(container.getProject()).createExpressionFromText(newValue, container.getParent()));
            }

            @NotNull
            @Override
            public Object[] getVariants() {
              return EMPTY_ARRAY;
            }
          }
        };
      }
    });

    registrar.registerReferenceProvider(javaFile, new PsiReferenceProvider() {
      @NotNull
      @Override
      public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
        if (!PsiUtil.isIdeaProject(element.getProject())) return PsiReference.EMPTY_ARRAY;
        return new FileReferenceSet(element) {
          @Override
          protected Collection<PsiFileSystemItem> getExtraContexts() {
            final Module icons = ModuleManager.getInstance(element.getProject()).findModuleByName("icons");
            if (icons != null) {
              final ArrayList<PsiFileSystemItem> result = new ArrayList<PsiFileSystemItem>();
              final VirtualFile[] roots = ModuleRootManager.getInstance(icons).getSourceRoots();
              final PsiManager psiManager = element.getManager();
              for (VirtualFile root : roots) {
                final PsiDirectory directory = psiManager.findDirectory(root);
                if (directory != null) {
                  result.add(directory);
                }
              }
              return result;
            }
            return super.getExtraContexts();
          }
        }.getAllReferences();
      }
    });

    registrar.registerReferenceProvider(pluginXml, new PsiReferenceProvider() {
      @NotNull
      @Override
      public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
        return new PsiReference[] {
          new PsiReferenceBase<PsiElement>(element, true) {
            @Override
            public PsiElement resolve() {
              String value = ((XmlAttributeValue)element).getValue();
              if (value.startsWith("/")) {
                FileReference lastRef = new FileReferenceSet(element).getLastReference();
                return lastRef != null ? lastRef.resolve() : null;
              }
              else {
                List<String> path = StringUtil.split(value, ".");
                if (path.size() > 1 && path.get(0).endsWith("Icons")) {
                  Project project = element.getProject();
                  PsiClass cur = JavaPsiFacade.getInstance(project).findClass(fqnIconsClass(path.get(0)),
                                                                             GlobalSearchScope.projectScope(project));
                  if (cur == null) return null;

                  for (int i = 1; i < path.size() - 1; i++) {
                    cur = cur.findInnerClassByName(path.get(i), false);
                    if (cur == null) return null;
                  }

                  return cur.findFieldByName(path.get(path.size() - 1), false);
                }
              }

              return null;
            }

            @Override
            public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
              PsiElement element = resolve();
              if (element instanceof PsiFile) {
                FileReference lastRef = new FileReferenceSet(element).getLastReference();
                return lastRef.handleElementRename(newElementName);
              }
              else if (element instanceof PsiField) {
                String fqn = ((PsiField)element).getContainingClass().getQualifiedName();

                if (fqn.startsWith("com.intellij.icons.")) {
                  return replace(fqn, newElementName, "com.intellij.icons.");
                }
                else if (fqn.startsWith("icons.")) {
                  return replace(fqn, newElementName, "icons.");
                }
              }

              return super.handleElementRename(newElementName);
            }

            @Override
            public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
              if (element instanceof PsiFile) {
                FileReference lastRef = new FileReferenceSet(element).getLastReference();
                return lastRef.bindToElement(element);
              }
              else if (element instanceof PsiField) {
                String fqn = ((PsiField)element).getContainingClass().getQualifiedName();

                String newName = ((PsiField)element).getName();
                if (fqn.startsWith("com.intellij.icons.")) {
                  return replace(fqn, newName, "com.intellij.icons.");
                }
                else if (fqn.startsWith("icons.")) {
                  return replace(fqn, newName, "icons.");
                }
              }

              return super.bindToElement(element);
            }

            private PsiElement replace(String fqn, String newName, String pckg) {
              XmlAttribute parent = (XmlAttribute)getElement().getParent();
              parent.setValue(fqn.substring(pckg.length()) + "." + newName);
              return parent.getValueElement();
            }

            @NotNull
            @Override
            public Object[] getVariants() {
              return EMPTY_ARRAY;
            }
          }
        };
      }
    });
  }

  private static String fqnIconsClass(String className) {
    return "AllIcons".equals(className) ? "com.intellij.icons.AllIcons" : "icons." + className;
  }

  @Override
  public boolean execute(@NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull final Processor<PsiReference> consumer) {
    final PsiElement file = queryParameters.getElementToSearch();
    if (file instanceof PsiBinaryFile) {
      final Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
        @Override
        public Module compute() {
          return ModuleUtilCore.findModuleForPsiElement(file);
        }
      });

      final VirtualFile image = ((PsiBinaryFile)file).getVirtualFile();
      if (isImage(image) && isIconsModule(module)) {
        final Project project = file.getProject();
        final FindModel model = new FindModel();
        final String path = getPathToImage(image, module);
        if (path == null) return true;
        model.setStringToFind(path);
        model.setCaseSensitive(true);
        model.setFindAll(true);
        model.setWholeWordsOnly(true);
        FindInProjectUtil.findUsages(model, FindInProjectUtil.getPsiDirectory(model, project), project, new Processor<UsageInfo>() {
          @Override
          public boolean process(final UsageInfo usage) {
            ApplicationManager.getApplication().runReadAction(new Runnable() {
              public void run() {
                final PsiElement element = usage.getElement();

                final ProperTextRange textRange = usage.getRangeInElement();
                if (element != null && textRange != null) {
                  final PsiElement start = element.findElementAt(textRange.getStartOffset());
                  final PsiElement end = element.findElementAt(textRange.getEndOffset());
                  if (start != null && end != null) {
                    PsiElement value = PsiTreeUtil.findCommonParent(start, end);
                    if (value instanceof PsiJavaToken) {
                      value = value.getParent();
                    }
                    if (value != null) {
                      final PsiFileReference reference = FileReferenceUtil.findFileReference(value);
                      if (reference != null) {
                        consumer.process(reference);
                      }
                    }
                  }
                }
              }
            });
            return true;
          }
        }, new FindUsagesProcessPresentation(new UsageViewPresentation()));
      }
    }
    return true;
  }

  @Nullable
  private static String getPathToImage(VirtualFile image, Module module) {
    final String path = ModuleRootManager.getInstance(module).getSourceRoots()[0].getPath();
    return "/" + FileUtil.getRelativePath(path, image.getPath(), '/');
  }

  private static boolean isIconsModule(Module module) {
    return module != null && "icons".equals(module.getName())
           && ModuleRootManager.getInstance(module).getSourceRoots().length == 1;
  }

  private static boolean isImage(VirtualFile image) {
    final FileTypeManager mgr = FileTypeManager.getInstance();
    return image != null && mgr.getFileTypeByFile(image) == mgr.getFileTypeByExtension("png");
  }
}
