/*
 * 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.actions.generate.equals;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.actions.generate.GroovyCodeInsightBundle;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;

import java.text.MessageFormat;
import java.util.*;

/**
 * User: Dmitry.Krasilschikov
 * Date: 02.06.2008
 */
public class GroovyGenerateEqualsHelper {
  private static final Logger LOG = Logger.getInstance(GroovyGenerateEqualsHelper.class);

  private final PsiClass myClass;
  private final PsiField[] myEqualsFields;
  private final PsiField[] myHashCodeFields;
  private final HashSet<PsiField> myNonNullSet;
  private final GroovyPsiElementFactory myFactory;
  private String myParameterName;

  @NonNls private static final String BASE_OBJECT_PARAMETER_NAME = "object";
  @NonNls private static final String BASE_OBJECT_LOCAL_NAME = "that";
  @NonNls private static final String RESULT_VARIABLE = "result";
  @NonNls private static final String TEMP_VARIABLE = "temp";

  private String myClassInstanceName;

  @NonNls
  private static final HashMap<String, MessageFormat> PRIMITIVE_HASHCODE_FORMAT = new HashMap<String, MessageFormat>();
  private final boolean mySuperHasHashCode;
//  private CodeStyleManager myCodeStyleManager;

  private final Project myProject;
  private final boolean myCheckParameterWithInstanceof;

  public GroovyGenerateEqualsHelper(Project project,
                                    PsiClass aClass,
                                    PsiField[] equalsFields,
                                    PsiField[] hashCodeFields,
                                    PsiField[] nonNullFields,
                                    boolean useInstanceofToCheckParameterType) {
    myClass = aClass;
    myEqualsFields = equalsFields;
    myHashCodeFields = hashCodeFields;
    myProject = project;
    myCheckParameterWithInstanceof = useInstanceofToCheckParameterType;

    myNonNullSet = new HashSet<PsiField>();
    ContainerUtil.addAll(myNonNullSet, nonNullFields);

    myFactory = GroovyPsiElementFactory.getInstance(project);

    mySuperHasHashCode = superMethodExists(getHashCodeSignature());
//    myCodeStyleManager = CodeStyleManager.getInstance(myProject);
  }

  private static String getUniqueLocalVarName(String base, PsiField[] fields) {
    String id = base;
    int index = 0;
    while (true) {
      if (index > 0) {
        id = base + index;
      }
      index++;
      boolean anyEqual = false;
      for (PsiField equalsField : fields) {
        if (id.equals(equalsField.getName())) {
          anyEqual = true;
          break;
        }
      }
      if (!anyEqual) break;
    }


    return id;
  }

  public void run() {
    try {
      final Collection<PsiMethod> members = generateMembers();
      for (PsiElement member : members) {
        myClass.add(member);
      }
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }

  public Collection<PsiMethod> generateMembers() throws IncorrectOperationException {
    PsiMethod equals = null;
    if (myEqualsFields != null && findMethod(myClass, getEqualsSignature(myProject, myClass.getResolveScope())) == null) {
      equals = createEquals();
    }

    PsiMethod hashCode = null;
    if (myHashCodeFields != null && findMethod(myClass, getHashCodeSignature()) == null) {
      if (myHashCodeFields.length > 0) {
        hashCode = createHashCode();
      } else {
        hashCode = myFactory.createMethodFromText("int hashCode() {\nreturn 0\n}");
        if (!mySuperHasHashCode) {
          //    reformatCode(hashCode);
        }
      }
    }
    if (hashCode != null && equals != null) {
      return Arrays.asList(equals, hashCode);
    } else if (equals != null) {
      return Collections.singletonList(equals);
    } else if (hashCode != null) {
      return Collections.singletonList(hashCode);
    } else {
      return Collections.emptyList();
    }
  }


  private void addDoubleFieldComparison(final StringBuffer buffer, final PsiField field) {
    @NonNls final String type = PsiType.DOUBLE.equals(field.getType()) ? "Double" : "Float";
    final Object[] parameters = new Object[]{type, myClassInstanceName, field.getName()};
    DOUBLE_FIELD_COMPARER_MF.format(parameters, buffer, null);
  }

  @NonNls private static final MessageFormat ARRAY_COMPARER_MF = new MessageFormat("if (!java.util.Arrays.equals({1}, {0}.{1})) return false\n");
  @NonNls private static final MessageFormat FIELD_COMPARER_MF = new MessageFormat("if ({1} != {0}.{1}) return false\n");
  @NonNls private static final MessageFormat DOUBLE_FIELD_COMPARER_MF = new MessageFormat("if ({0}.compare({1}.{2}, {2}) != 0) return false\n");

  private void addArrayEquals(StringBuffer buffer, PsiField field) {
    final PsiType fieldType = field.getType();
    if (isNestedArray(fieldType)) {
      buffer.append(" ");
      buffer.append(GroovyCodeInsightBundle.message("generate.equals.compare.nested.arrays.comment", field.getName()));
      buffer.append("\n");
      return;
    }
    if (isArrayOfObjects(fieldType)) {
      buffer.append(" ");
      buffer.append(GroovyCodeInsightBundle.message("generate.equals.compare.arrays.comment"));
      buffer.append("\n");
    }

    ARRAY_COMPARER_MF.format(getComparerFormatParameters(field), buffer, null);
  }

  private Object[] getComparerFormatParameters(PsiField field) {
    return new Object[]{myClassInstanceName, field.getName()};
  }

  private void addFieldComparison(StringBuffer buffer, PsiField field) {
    FIELD_COMPARER_MF.format(getComparerFormatParameters(field), buffer, null);
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private void addInstanceOfToText(@NonNls StringBuffer buffer, String returnValue) {
    if (myCheckParameterWithInstanceof) {
      buffer.append("if (!(").append(myParameterName).append(" instanceof ").append(myClass.getName()).append(")) " + "return ")
        .append(returnValue).append('\n');
    } else {
      buffer.append("if (").append("getClass() != ").append(myParameterName).append(".class) " + "return ").append(returnValue)
        .append('\n');
    }
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private void addEqualsPrologue(@NonNls StringBuffer buffer) {
    buffer.append("if (this.is(").append(myParameterName).append(")").append(") return true\n");
    if (!superMethodExists(getEqualsSignature(myProject, myClass.getResolveScope()))) {
      addInstanceOfToText(buffer, Boolean.toString(false));
    } else {
      addInstanceOfToText(buffer, Boolean.toString(false));
      buffer.append("if (!super.equals(");
      buffer.append(myParameterName);
      buffer.append(")) return false\n");
    }
  }

  private void addClassInstance(@NonNls StringBuffer buffer) {
    buffer.append("\n");
    // A a = (A) object;
    CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myProject);
    if (settings.GENERATE_FINAL_LOCALS) {
      buffer.append("final ");
    }

    buffer.append(myClass.getName());
    buffer.append(" ").append(myClassInstanceName).append(" = (");
    buffer.append(myClass.getName());
    buffer.append(")");
    buffer.append(myParameterName);
    buffer.append("\n\n");
  }

  private boolean superMethodExists(MethodSignature methodSignature) {
    LOG.assertTrue(myClass.isValid());
    PsiMethod superEquals = MethodSignatureUtil.findMethodBySignature(myClass, methodSignature, true);
    if (superEquals == null) return true;
    if (superEquals.hasModifierProperty(PsiModifier.ABSTRACT)) return false;
    return !CommonClassNames.JAVA_LANG_OBJECT.equals(superEquals.getContainingClass().getQualifiedName());
  }


  private PsiMethod createEquals() throws IncorrectOperationException {
    final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myProject);
    String[] nameSuggestions = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, PsiType.getJavaLangObject(myClass.getManager(), myClass.getResolveScope())).names;
    final String objectBaseName = nameSuggestions.length > 0 ? nameSuggestions[0] : BASE_OBJECT_PARAMETER_NAME;
    myParameterName = getUniqueLocalVarName(objectBaseName, myEqualsFields);
    //todo isApplicable it
    final PsiType classType = TypesUtil.createType(myClass.getQualifiedName(), myClass.getContext());

    nameSuggestions = codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, classType).names;
    String instanceBaseName = nameSuggestions.length > 0 && nameSuggestions[0].length() < 10 ? nameSuggestions[0] : BASE_OBJECT_LOCAL_NAME;
    myClassInstanceName = getUniqueLocalVarName(instanceBaseName, myEqualsFields);

    @NonNls StringBuffer buffer = new StringBuffer();
    buffer.append("boolean equals(").append(myParameterName).append(") {\n");
    addEqualsPrologue(buffer);
    if (myEqualsFields.length > 0) {
      addClassInstance(buffer);

      ArrayList<PsiField> equalsFields = new ArrayList<PsiField>();
      ContainerUtil.addAll(equalsFields, myEqualsFields);
      Collections.sort(equalsFields, EqualsFieldsComparator.INSTANCE);

      for (PsiField field : equalsFields) {
        if (!field.hasModifierProperty(PsiModifier.STATIC)) {
          final PsiType type = field.getType();
          if (type instanceof PsiArrayType) {
            addArrayEquals(buffer, field);
          }
          else if (type instanceof PsiPrimitiveType) {
            if (PsiType.DOUBLE.equals(type) || PsiType.FLOAT.equals(type)) {
              addDoubleFieldComparison(buffer, field);
            }
            else {
              addFieldComparison(buffer, field);
            }
          }
          else {
            if (type instanceof PsiClassType) {
              final PsiClass aClass = ((PsiClassType)type).resolve();
              if (aClass != null && aClass.isEnum()) {
                addFieldComparison(buffer, field);
                continue;
              }
            }
            addFieldComparison(buffer, field);
          }
        }
      }
    }
    buffer.append("\nreturn true\n}");

    GrMethod result = myFactory.createMethodFromText(buffer.toString());
    final PsiParameter parameter = result.getParameterList().getParameters()[0];
    PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL, CodeStyleSettingsManager.getSettings(myProject).GENERATE_FINAL_PARAMETERS);

    try {
      result = ((GrMethod) CodeStyleManager.getInstance(myProject).reformat(result));
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }

    return result;
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private PsiMethod createHashCode() throws IncorrectOperationException {

    StringBuilder buffer = StringBuilderSpinAllocator.alloc();

    try {
      buffer.append("int hashCode() {\n");
      if (!mySuperHasHashCode && myHashCodeFields.length == 1) {
        PsiField field = myHashCodeFields[0];
        final String tempName = addTempForOneField(field, buffer);
        buffer.append("return ");
        if (field.getType() instanceof PsiPrimitiveType) {
          addPrimitiveFieldHashCode(buffer, field, tempName);
        } else {
          addFieldHashCode(buffer, field);
        }
        buffer.append("\n}");
      } else if (myHashCodeFields.length > 0) {
        CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myProject);
        final String resultName = getUniqueLocalVarName(settings.LOCAL_VARIABLE_NAME_PREFIX + RESULT_VARIABLE, myHashCodeFields);

        buffer.append("int ");
        buffer.append(resultName);

        boolean resultAssigned = false;
        if (mySuperHasHashCode) {
          buffer.append(" = ");
          addSuperHashCode(buffer);
          resultAssigned = true;
        }
        buffer.append("\n");
        String tempName = addTempDeclaration(buffer);
        for (PsiField field : myHashCodeFields) {
          addTempAssignment(field, buffer, tempName);
          buffer.append(resultName);
          buffer.append(" = ");
          if (resultAssigned) {
            buffer.append("31 * ");
            buffer.append(resultName);
            buffer.append(" + ");
          }
          if (field.getType() instanceof PsiPrimitiveType) {
            addPrimitiveFieldHashCode(buffer, field, tempName);
          } else {
            addFieldHashCode(buffer, field);
          }
          buffer.append('\n');
          resultAssigned = true;
        }
        buffer.append("return ");
        buffer.append(resultName);
        buffer.append("\n}");
      } else {
        buffer.append("return 0\n}");
      }
      PsiMethod hashCode = myFactory.createMethodFromText(buffer.toString());

      try {
        hashCode = ((GrMethod) CodeStyleManager.getInstance(myProject).reformat(hashCode));
      } catch (IncorrectOperationException e) {
        LOG.error(e);
      }

//      reformatCode(hashCode);
      return hashCode;
    }
    finally {
      StringBuilderSpinAllocator.dispose(buffer);
    }
  }

  private static void addTempAssignment(PsiField field, StringBuilder buffer, String tempName) {
    if (PsiType.DOUBLE.equals(field.getType())) {
      buffer.append(tempName);
      addTempForDoubleInitialization(field, buffer);
    }
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private static void addTempForDoubleInitialization(PsiField field, StringBuilder buffer) {
    buffer.append(" = ").append(field.getName()).append(" != +0.0d ? Double.doubleToLongBits(");
    buffer.append(field.getName());
    buffer.append(") : 0L\n");
  }

  @Nullable
  @SuppressWarnings("HardCodedStringLiteral")
  private String addTempDeclaration(StringBuilder buffer) {
    for (PsiField hashCodeField : myHashCodeFields) {
      if (PsiType.DOUBLE.equals(hashCodeField.getType())) {
        final String name = getUniqueLocalVarName(TEMP_VARIABLE, myHashCodeFields);
        buffer.append("long ").append(name).append("\n");
        return name;
      }
    }
    return null;
  }

  @Nullable
  @SuppressWarnings("HardCodedStringLiteral")
  private String addTempForOneField(PsiField field, StringBuilder buffer) {
    if (PsiType.DOUBLE.equals(field.getType())) {
      final String name = getUniqueLocalVarName(TEMP_VARIABLE, myHashCodeFields);
      CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myProject);
      if (settings.GENERATE_FINAL_LOCALS) {
        buffer.append("final ");
      }
      buffer.append("long ").append(name);
      addTempForDoubleInitialization(field, buffer);
      return name;
    }
    else {
      return null;
    }
  }

  private static void addPrimitiveFieldHashCode(StringBuilder buffer, PsiField field, String tempName) {
    MessageFormat format = PRIMITIVE_HASHCODE_FORMAT.get(field.getType().getCanonicalText());
    buffer.append(format.format(new Object[]{field.getName(), tempName}));
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private void addFieldHashCode(StringBuilder buffer, PsiField field) {
    final String name = field.getName();
    if (myNonNullSet.contains(field)) {
      adjustHashCodeToArrays(buffer, field, name);
    } else {
      buffer.append("(");
      buffer.append(name);
      buffer.append(" != null ? ");
      adjustHashCodeToArrays(buffer, field, name);
      buffer.append(" : 0)");
    }
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private static void adjustHashCodeToArrays(StringBuilder buffer, final PsiField field, final String name) {
    if (field.getType() instanceof PsiArrayType && LanguageLevel.JDK_1_5.compareTo(PsiUtil.getLanguageLevel(field)) <= 0) {
      buffer.append("Arrays.hashCode(");
      buffer.append(name);
      buffer.append(")");
    } else {
      buffer.append(name);
      buffer.append(".hashCode()");
    }
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private void addSuperHashCode(StringBuilder buffer) {
    if (mySuperHasHashCode) {
      buffer.append("super.hashCode()");
    } else {
      buffer.append("0");
    }
  }

  @Nullable
  static PsiMethod findMethod(PsiClass aClass, MethodSignature signature) {
    return MethodSignatureUtil.findMethodBySignature(aClass, signature, false);
  }

  static class EqualsFieldsComparator implements Comparator<PsiField> {
    public static final EqualsFieldsComparator INSTANCE = new EqualsFieldsComparator();

    @Override
    public int compare(PsiField f1, PsiField f2) {
      if (f1.getType() instanceof PsiPrimitiveType && !(f2.getType() instanceof PsiPrimitiveType)) return -1;
      if (!(f1.getType() instanceof PsiPrimitiveType) && f2.getType() instanceof PsiPrimitiveType) return 1;
      final String name1 = f1.getName();
      final String name2 = f2.getName();
      assert name1 != null && name2 != null;
      return name1.compareTo(name2);
    }
  }

  static {
    initPrimitiveHashcodeFormats();
  }

  @SuppressWarnings("HardCodedStringLiteral")
  private static void initPrimitiveHashcodeFormats() {
    PRIMITIVE_HASHCODE_FORMAT.put("byte", new MessageFormat("(int) {0}"));
    PRIMITIVE_HASHCODE_FORMAT.put("short", new MessageFormat("(int) {0}"));
    PRIMITIVE_HASHCODE_FORMAT.put("int", new MessageFormat("{0}"));
    PRIMITIVE_HASHCODE_FORMAT.put("long", new MessageFormat("(int) ({0} ^ ({0} >>> 32))"));
    PRIMITIVE_HASHCODE_FORMAT.put("boolean", new MessageFormat("({0} ? 1 : 0)"));

    PRIMITIVE_HASHCODE_FORMAT.put("float", new MessageFormat("({0} != +0.0f ? Float.floatToIntBits({0}) : 0)"));
    PRIMITIVE_HASHCODE_FORMAT.put("double", new MessageFormat("(int) ({1} ^ ({1} >>> 32))"));

    PRIMITIVE_HASHCODE_FORMAT.put("char", new MessageFormat("(int) {0}"));
    PRIMITIVE_HASHCODE_FORMAT.put("void", new MessageFormat("0"));
    PRIMITIVE_HASHCODE_FORMAT.put("void", new MessageFormat("({0} ? 1 : 0)"));
  }

  public static boolean isNestedArray(PsiType aType) {
    if (!(aType instanceof PsiArrayType)) return false;
    final PsiType componentType = ((PsiArrayType) aType).getComponentType();
    return componentType instanceof PsiArrayType;
  }

  public static boolean isArrayOfObjects(PsiType aType) {
    if (!(aType instanceof PsiArrayType)) return false;
    final PsiType componentType = ((PsiArrayType) aType).getComponentType();
    final PsiClass psiClass = PsiUtil.resolveClassInType(componentType);
    if (psiClass == null) return false;
    final String qName = psiClass.getQualifiedName();
    return CommonClassNames.JAVA_LANG_OBJECT.equals(qName);
  }

  public static MethodSignature getHashCodeSignature() {
    return MethodSignatureUtil.createMethodSignature("hashCode", PsiType.EMPTY_ARRAY, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
  }

  public static MethodSignature getEqualsSignature(Project project, GlobalSearchScope scope) {
    final PsiClassType javaLangObject = PsiType.getJavaLangObject(PsiManager.getInstance(project), scope);
    return MethodSignatureUtil
        .createMethodSignature("equals", new PsiType[]{javaLangObject}, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
  }
}
