/*
 * 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 com.intellij.psi.impl.source;

import com.intellij.openapi.util.SimpleModificationTracker;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.light.LightMethod;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import static com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT;

public class ClassInnerStuffCache {
  private final PsiExtensibleClass myClass;
  private final SimpleModificationTracker myTracker;

  public ClassInnerStuffCache(@NotNull PsiExtensibleClass aClass) {
    myClass = aClass;
    myTracker = new SimpleModificationTracker();
  }

  @NotNull
  public PsiMethod[] getConstructors() {
    return CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<PsiMethod[]>() {
      @Nullable
      @Override
      public Result<PsiMethod[]> compute() {
        return Result.create(PsiImplUtil.getConstructors(myClass), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    });
  }

  @NotNull
  public PsiField[] getFields() {
    return CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<PsiField[]>() {
      @Nullable
      @Override
      public Result<PsiField[]> compute() {
        return Result.create(getAllFields(), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    });
  }

  @NotNull
  public PsiMethod[] getMethods() {
    return CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<PsiMethod[]>() {
      @Nullable
      @Override
      public Result<PsiMethod[]> compute() {
        return Result.create(getAllMethods(), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    });
  }

  @NotNull
  public PsiClass[] getInnerClasses() {
    return CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<PsiClass[]>() {
      @Nullable
      @Override
      public Result<PsiClass[]> compute() {
        return Result.create(getAllInnerClasses(), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    });
  }

  @Nullable
  public PsiField findFieldByName(String name, boolean checkBases) {
    if (checkBases) {
      return PsiClassImplUtil.findFieldByName(myClass, name, true);
    }
    return CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<Map<String, PsiField>>() {
      @Nullable
      @Override
      public Result<Map<String, PsiField>> compute() {
        return Result.create(getFieldsMap(), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    }).get(name);
  }

  @NotNull
  public PsiMethod[] findMethodsByName(String name, boolean checkBases) {
    if (checkBases) {
      return PsiClassImplUtil.findMethodsByName(myClass, name, true);
    }
    PsiMethod[] methods = CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<Map<String, PsiMethod[]>>() {
      @Nullable
      @Override
      public Result<Map<String, PsiMethod[]>> compute() {
        return Result.create(getMethodsMap(), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    }).get(name);
    return methods == null ? PsiMethod.EMPTY_ARRAY : methods;
  }

  @Nullable
  public PsiClass findInnerClassByName(final String name, final boolean checkBases) {
    if (checkBases) {
      return PsiClassImplUtil.findInnerByName(myClass, name, true);
    }
    else {
      return CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<Map<String, PsiClass>>() {
        @Nullable
        @Override
        public Result<Map<String, PsiClass>> compute() {
          return Result.create(getInnerClassesMap(), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
        }
      }).get(name);
    }
  }

  @Nullable
  public PsiMethod getValuesMethod() {
    return !myClass.isEnum() || myClass.getName() == null ? null : CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<PsiMethod>() {
      @Nullable
      @Override
      public Result<PsiMethod> compute() {
        PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
        String text = "public static " + myClass.getName() + "[] values() { }";
        PsiMethod physicalMethod = factory.createMethodFromText(text, myClass);
        PsiMethod method = new LightMethod(myClass.getManager(), physicalMethod, myClass);
        return new Result<PsiMethod>(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    });
  }

  @Nullable
  public PsiMethod getValueOfMethod() {
    return !myClass.isEnum() || myClass.getName() == null ? null : CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<PsiMethod>() {
      @Nullable
      @Override
      public Result<PsiMethod> compute() {
        PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
        String text = "public static " + myClass.getName() + " valueOf(java.lang.String name) throws java.lang.IllegalArgumentException { }";
        PsiMethod physicalMethod = factory.createMethodFromText(text, myClass);
        PsiMethod method = new LightMethod(myClass.getManager(), physicalMethod, myClass);
        return new Result<PsiMethod>(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
      }
    });
  }

  @NotNull
  private PsiField[] getAllFields() {
    List<PsiField> own = myClass.getOwnFields();
    List<PsiField> ext = PsiAugmentProvider.collectAugments(myClass, PsiField.class);
    return ArrayUtil.mergeCollections(own, ext, PsiField.ARRAY_FACTORY);
  }

  @NotNull
  private PsiMethod[] getAllMethods() {
    List<PsiMethod> own = myClass.getOwnMethods();
    List<PsiMethod> ext = PsiAugmentProvider.collectAugments(myClass, PsiMethod.class);
    return ArrayUtil.mergeCollections(own, ext, PsiMethod.ARRAY_FACTORY);
  }

  @NotNull
  private PsiClass[] getAllInnerClasses() {
    List<PsiClass> own = myClass.getOwnInnerClasses();
    List<PsiClass> ext = PsiAugmentProvider.collectAugments(myClass, PsiClass.class);
    return ArrayUtil.mergeCollections(own, ext, PsiClass.ARRAY_FACTORY);
  }

  @NotNull
  private Map<String, PsiField> getFieldsMap() {
    PsiField[] fields = getFields();
    if (fields.length == 0) return Collections.emptyMap();

    Map<String, PsiField> cachedFields = new THashMap<String, PsiField>();
    for (PsiField field : fields) {
      String name = field.getName();
      if (!(field instanceof ExternallyDefinedPsiElement) || !cachedFields.containsKey(name)) {
        cachedFields.put(name, field);
      }
    }
    return cachedFields;
  }

  @NotNull
  private Map<String, PsiMethod[]> getMethodsMap() {
    PsiMethod[] methods = getMethods();
    if (methods.length == 0) return Collections.emptyMap();

    Map<String, List<PsiMethod>> collectedMethods = ContainerUtil.newHashMap();
    for (PsiMethod method : methods) {
      List<PsiMethod> list = collectedMethods.get(method.getName());
      if (list == null) {
        collectedMethods.put(method.getName(), list = ContainerUtil.newSmartList());
      }
      list.add(method);
    }

    Map<String, PsiMethod[]> cachedMethods = ContainerUtil.newTroveMap();
    for (Map.Entry<String, List<PsiMethod>> entry : collectedMethods.entrySet()) {
      List<PsiMethod> list = entry.getValue();
      cachedMethods.put(entry.getKey(), list.toArray(new PsiMethod[list.size()]));
    }
    return cachedMethods;
  }

  @NotNull
  private Map<String, PsiClass> getInnerClassesMap() {
    PsiClass[] classes = getInnerClasses();
    if (classes.length == 0) return Collections.emptyMap();

    Map<String, PsiClass> cachedInners = new THashMap<String, PsiClass>();
    for (PsiClass psiClass : classes) {
      String name = psiClass.getName();
      if (!(psiClass instanceof ExternallyDefinedPsiElement) || !cachedInners.containsKey(name)) {
        cachedInners.put(name, psiClass);
      }
    }
    return cachedInners;
  }

  public void dropCaches() {
    myTracker.incModificationCount();
  }
}
