/*
 * 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.plugins.groovy.refactoring;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyNamesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @author ilyas
 */
public class GroovyNameSuggestionUtil {

  public static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil");

  private GroovyNameSuggestionUtil() {
  }

  public static String[] suggestVariableNames(GrExpression expr, NameValidator validator) {
    return suggestVariableNames(expr, validator, false);
  }

  public static String[] suggestVariableNames(@NotNull GrExpression expr, NameValidator validator, boolean forStaticVariable) {
    Set<String> possibleNames = new LinkedHashSet<String>();
    PsiType type = expr.getType();
    generateNameByExpr(expr, possibleNames, validator, forStaticVariable);
    if (type != null && !PsiType.VOID.equals(type)) {
      generateVariableNameByTypeInner(type, possibleNames,validator);
    }

    possibleNames.remove("");
    if (possibleNames.isEmpty()) {
      possibleNames.add(validator.validateName("var", true));
    }
    return ArrayUtil.toStringArray(possibleNames);
  }

  public static String[] suggestVariableNameByType(PsiType type, NameValidator validator) {
    if (type == null) return ArrayUtil.EMPTY_STRING_ARRAY;
    Set<String> possibleNames = new LinkedHashSet<String>();
    generateVariableNameByTypeInner(type, possibleNames, validator);
    return ArrayUtil.toStringArray(possibleNames);
  }

  private static void generateVariableNameByTypeInner(PsiType type, Set<String> possibleNames, NameValidator validator) {
    String unboxed = PsiTypesUtil.unboxIfPossible(type.getCanonicalText());
    if (unboxed != null && !unboxed.equals(type.getCanonicalText())) {
      String name = generateNameForBuiltInType(unboxed);
      name = validator.validateName(name, true);
      if (GroovyNamesUtil.isIdentifier(name)) {
        possibleNames.add(name);
      }
    }
    else if (type instanceof PsiIntersectionType) {
      for (PsiType psiType : ((PsiIntersectionType)type).getConjuncts()) {
        generateByType(psiType, possibleNames, validator);
      }
    }
    else {
      generateByType(type, possibleNames, validator);
    }
  }

  private static void generateNameByExpr(GrExpression expr, Set<String> possibleNames, NameValidator validator, boolean forStaticVariable) {
    if (expr instanceof GrReferenceExpression && ((GrReferenceExpression) expr).getReferenceName() != null) {
      if (PsiUtil.isThisReference(expr)) {
        possibleNames.add(validator.validateName("thisInstance", true));
      }
      if (PsiUtil.isSuperReference(expr)) {
        possibleNames.add(validator.validateName("superInstance", true));
      }
      GrReferenceExpression refExpr = (GrReferenceExpression) expr;
      String name = refExpr.getReferenceName();
      if (name != null && name.toUpperCase().equals(name)) {
        possibleNames.add(validator.validateName(name.toLowerCase(), true));
      } else {
        generateCamelNames(possibleNames, validator, name);
      }
      if (expr.getText().equals(name)) {
        possibleNames.remove(name);
      }
    }
    if (expr instanceof GrMethodCallExpression) {
      generateNameByExpr(((GrMethodCallExpression) expr).getInvokedExpression(), possibleNames, validator, forStaticVariable);
    }
    if (expr instanceof GrLiteral) {
      final Object value = ((GrLiteral)expr).getValue();
      if (value instanceof String) {
        generateNameByString(possibleNames, (String)value, validator, forStaticVariable, expr.getProject());
      }
    }
  }

  private static void generateNameByString(Set<String> possibleNames,
                                           String value,
                                           NameValidator validator,
                                           boolean forStaticVariable,
                                           Project project) {
    if (!PsiNameHelper.getInstance(project).isIdentifier(value)) return;
    if (forStaticVariable) {
      StringBuilder buffer = new StringBuilder(value.length() + 10);
      char[] chars = new char[value.length()];
      value.getChars(0, value.length(), chars, 0);
      boolean wasLow = Character.isLowerCase(chars[0]);

      buffer.append(Character.toUpperCase(chars[0]));
      for (int i = 1; i < chars.length; i++) {
        if (Character.isUpperCase(chars[i])) {
          if (wasLow) {
            buffer.append('_');
            wasLow = false;
          }
        }
        else {
          wasLow = true;
        }

        buffer.append(Character.toUpperCase(chars[i]));
      }
      possibleNames.add(validator.validateName(buffer.toString(), true));
    }
    else {
      possibleNames.add(validator.validateName(value, true));
    }
  }

  private static void generateByType(PsiType type, Set<String> possibleNames, NameValidator validator) {
    String typeName = type.getPresentableText();
    generateNamesForCollectionType(type, possibleNames, validator);
    generateNamesForArrayType(type, possibleNames, validator);
    generateNamesForExceptions(type, possibleNames, validator);
    typeName = cleanTypeName(typeName);
    if (typeName.equals("String")) {
      possibleNames.add(validator.validateName("s", true));
    }
    if (typeName.equals("Closure")) {
      possibleNames.add(validator.validateName("cl", true));
    }
    if (typeName.toUpperCase().equals(typeName)) {
      possibleNames.add(validator.validateName(GroovyNamesUtil.deleteNonLetterFromString(typeName.toLowerCase()), true));
    } else if (!typeName.equals(typeName.toLowerCase())) {
      generateCamelNames(possibleNames, validator, typeName);
      possibleNames.remove(typeName);
    }
  }

  private static void generateNamesForExceptions(PsiType type, Set<String> possibleNames, NameValidator validator) {
    if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ERROR)) {
      possibleNames.add(validator.validateName("error", true));
    }
    else if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_EXCEPTION)) {
      possibleNames.add(validator.validateName("e", true));
    }
  }

  private static void generateNamesForArrayType(PsiType type, Set<String> possibleNames, NameValidator validator) {
    int arrayDim = type.getArrayDimensions();
    if (arrayDim == 0) return;
    PsiType deepType = type.getDeepComponentType();
    String candidateName = cleanTypeName(deepType.getPresentableText());
    if (deepType instanceof PsiClassType) {
      PsiClass clazz = ((PsiClassType) deepType).resolve();
      if (clazz == null) return;
      candidateName = GroovyNamesUtil.fromLowerLetter(clazz.getName());
    }
    candidateName = StringUtil.pluralize(GroovyNamesUtil.fromLowerLetter(candidateName));
    generateCamelNames(possibleNames, validator, candidateName);

    ArrayList<String> camelizedName = GroovyNamesUtil.camelizeString(candidateName);
    candidateName = camelizedName.get(camelizedName.size() - 1);
    candidateName = "arrayOf" + fromUpperLetter(candidateName);
    possibleNames.add(validator.validateName(candidateName, true));
  }

  private static void generateNamesForCollectionType(PsiType type, Set<String> possibleNames, NameValidator validator) {
    PsiType componentType = getCollectionComponentType(type, validator.getProject());
    if (!(type instanceof PsiClassType) || componentType == null) return;
    PsiClass clazz = ((PsiClassType) type).resolve();
    if (clazz == null) return;
    String collectionName = clazz.getName();
    assert collectionName != null;

    String componentName = cleanTypeName(componentType.getPresentableText());
    if (componentType instanceof PsiClassType) {
      PsiClassType classType = (PsiClassType) componentType;
      PsiClass psiClass = classType.resolve();
      if (psiClass == null) return;
      componentName = psiClass.getName();
    }

    assert componentName != null;
    String candidateName = StringUtil.pluralize(GroovyNamesUtil.fromLowerLetter(componentName));
    generateCamelNames(possibleNames, validator, candidateName);

    ArrayList<String> camelizedName = GroovyNamesUtil.camelizeString(candidateName);
    candidateName = camelizedName.get(camelizedName.size() - 1);
    candidateName = collectionName.toLowerCase() + "Of" + fromUpperLetter(candidateName);
    possibleNames.add(validator.validateName(candidateName, true));
  }

  @NotNull
  private static String cleanTypeName(@NotNull String typeName) {
    if (typeName.contains(".")) {
      typeName = typeName.substring(typeName.lastIndexOf(".") + 1);
    }
    if (typeName.contains("<")) {
      typeName = typeName.substring(0, typeName.indexOf("<"));
    }
    return typeName;
  }

  private static void generateCamelNames(Set<String> possibleNames, NameValidator validator, String typeName) {
    ArrayList<String> camelTokens = GroovyNamesUtil.camelizeString(typeName);
    Collections.reverse(camelTokens);
    if (!camelTokens.isEmpty()) {
      String possibleName = "";
      for (String camelToken : camelTokens) {
        possibleName = camelToken + fromUpperLetter(possibleName);
        String candidate = validator.validateName(possibleName, true);
        // todo generify
        if (candidate.equals("class")) {
          candidate = validator.validateName("clazz", true);
        }
        if (!possibleNames.contains(candidate) && GroovyNamesUtil.isIdentifier(candidate)) {
          possibleNames.add(candidate);
        }
      }
    }
  }

  private static String generateNameForBuiltInType(String unboxed) {
    return unboxed.toLowerCase().substring(0, 1);
  }

  private static String fromUpperLetter(String str) {
    if (str.isEmpty()) return "";
    if (str.length() == 1) return str.toUpperCase();
    return str.substring(0, 1).toUpperCase() + str.substring(1);
  }

  @Nullable
  private static PsiType getCollectionComponentType(PsiType type, Project project) {
    if (!(type instanceof PsiClassType)) return null;
    PsiClassType classType = (PsiClassType) type;
    PsiClassType.ClassResolveResult result = classType.resolveGenerics();
    PsiClass clazz = result.getElement();
    if (clazz == null) return null;
    JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
    @SuppressWarnings({"ConstantConditions"}) PsiClass collectionClass = facade.findClass("java.util.Collection", type.getResolveScope());
    if (collectionClass == null || collectionClass.getTypeParameters().length != 1) return null;
    PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(collectionClass, clazz, result.getSubstitutor());

    if (substitutor == null) return null;
    PsiType componentType = substitutor.substitute(collectionClass.getTypeParameters()[0]);
    return componentType instanceof PsiIntersectionType ? null : componentType;
  }
}
