/*
 * Copyright 2000-2012 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.codeInspection.i18n.folding;

import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
import com.intellij.codeInspection.i18n.JavaI18nUtil;
import com.intellij.lang.ASTNode;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.folding.FoldingBuilderEx;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.parsing.PropertiesElementTypes;
import com.intellij.lang.properties.psi.Property;
import com.intellij.lang.properties.psi.impl.PropertyImpl;
import com.intellij.lang.properties.psi.impl.PropertyStubImpl;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author Konstantin Bulenkov
 */
public class PropertyFoldingBuilder extends FoldingBuilderEx {
  private static final int FOLD_MAX_LENGTH = 50;
  private static final Key<IProperty> CACHE = Key.create("i18n.property.cache");
  public static final IProperty NULL = new PropertyImpl(new PropertyStubImpl(null, null), PropertiesElementTypes.PROPERTY);

  @Override
  @NotNull
  public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement element, @NotNull Document document, boolean quick) {
    if (!(element instanceof PsiJavaFile) || quick || !isFoldingsOn()) {
      return FoldingDescriptor.EMPTY;
    }
    final PsiJavaFile file = (PsiJavaFile) element;
    final Project project = file.getProject();
    final List<FoldingDescriptor> result = new ArrayList<FoldingDescriptor>();
    boolean hasJsp = ContainerUtil.intersects(Arrays.asList(StdLanguages.JSP, StdLanguages.JSPX), file.getViewProvider().getLanguages());
    //hack here because JspFile PSI elements are not threaded correctly via nextSibling/prevSibling
    file.accept(hasJsp ? new JavaRecursiveElementVisitor() {
      @Override
      public void visitLiteralExpression(PsiLiteralExpression expression) {
        checkLiteral(project, expression, result);
      }
    } : new JavaRecursiveElementWalkingVisitor() {
      @Override
      public void visitLiteralExpression(PsiLiteralExpression expression) {
        checkLiteral(project, expression, result);
      }
    });

    return result.toArray(new FoldingDescriptor[result.size()]);
  }

  private static boolean isFoldingsOn() {
    return JavaCodeFoldingSettings.getInstance().isCollapseI18nMessages();
  }

  private static void checkLiteral(Project project, PsiLiteralExpression expression, List<FoldingDescriptor> result) {
    if (isI18nProperty(project, expression)) {
      final IProperty property = getI18nProperty(project, expression);
      final HashSet<Object> set = new HashSet<Object>();
      set.add(property != null ? property : PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
      final String msg = formatI18nProperty(expression, property);

      final PsiElement parent = expression.getParent();
      if (!msg.equals(expression.getText()) &&
          parent instanceof PsiExpressionList &&
          ((PsiExpressionList)parent).getExpressions()[0] == expression) {
        final PsiExpressionList expressions = (PsiExpressionList)parent;
        final int count = JavaI18nUtil.getPropertyValueParamsMaxCount(expression);
        final PsiExpression[] args = expressions.getExpressions();
        if (args.length == 1 + count && parent.getParent() instanceof PsiMethodCallExpression) {
          boolean ok = true;
          for (int i = 1; i < count + 1; i++) {
            Object value = JavaConstantExpressionEvaluator.computeConstantExpression(args[i], false);
            if (value == null) {
              if (!(args[i] instanceof PsiReferenceExpression)) {
                ok = false;
                break;
              }
            }
          }
          if (ok) {
            result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(parent.getParent().getNode()), parent.getParent().getTextRange(), null, set));
            return;
          }
        }
      }

      result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(expression.getNode()), expression.getTextRange(), null, set));
    }
  }


  @Override
  public String getPlaceholderText(@NotNull ASTNode node) {
    final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(node);
    if (element instanceof PsiLiteralExpression) {
      return getI18nMessage(element.getProject(), (PsiLiteralExpression)element);
    } else if (element instanceof PsiMethodCallExpression) {
      return formatMethodCallExpression(element.getProject(), (PsiMethodCallExpression)element);
    }
    return element.getText();
  }

  private static String formatMethodCallExpression(Project project, PsiMethodCallExpression methodCallExpression) {
    final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions();
    if (args.length > 0
        && args[0] instanceof PsiLiteralExpression
        && args[0].isValid()
        && isI18nProperty(project, (PsiLiteralExpression)args[0])) {
      final int count = JavaI18nUtil.getPropertyValueParamsMaxCount((PsiLiteralExpression)args[0]);
      if (args.length == 1 + count) {
        String text = getI18nMessage(project, (PsiLiteralExpression)args[0]);
        for (int i = 1; i < count + 1; i++) {
          Object value = JavaConstantExpressionEvaluator.computeConstantExpression(args[i], false);
          if (value == null) {
            if (args[i] instanceof PsiReferenceExpression) {
              value = "{" + args[i].getText() + "}";
            }
            else {
              text = null;
              break;
            }
          }
          text = text.replace("{" + (i - 1) + "}", value.toString());
        }
        if (text != null) {
          if (!text.equals(methodCallExpression.getText())) {
            text = text.replace("''", "'");
          }
          return text.length() > FOLD_MAX_LENGTH ? text.substring(0, FOLD_MAX_LENGTH - 3) + "...\"" : text;
        }
      }
    }

    return methodCallExpression.getText();
  }

  private static String getI18nMessage(@NotNull Project project, PsiLiteralExpression literal) {
    final IProperty property = getI18nProperty(project, literal);
    return property == null ? literal.getText() : formatI18nProperty(literal, property);
  }

  @Nullable
  private static IProperty getI18nProperty(Project project, PsiLiteralExpression literal) {
    final Property property = (Property)literal.getUserData(CACHE);
    if (property == NULL) return null;
    if (property != null && isValid(property, literal)) return property;
    if (isI18nProperty(project, literal)) {
      final PsiReference[] references = literal.getReferences();
      for (PsiReference reference : references) {
        if (reference instanceof PsiPolyVariantReference) {
          final ResolveResult[] results = ((PsiPolyVariantReference)reference).multiResolve(false);
          for (ResolveResult result : results) {
            final PsiElement element = result.getElement();
            if (element instanceof IProperty) {
              IProperty p = (IProperty)element;
              literal.putUserData(CACHE, p);
              return p;
            }
          }
        } else {
          final PsiElement element = reference.resolve();
          if (element instanceof IProperty) {
            IProperty p = (IProperty)element;
            literal.putUserData(CACHE, p);
            return p;
          }
        }
      }
    }
    return null;
  }

  private static boolean isValid(Property property, PsiLiteralExpression literal) {
    if (literal == null || property == null || !property.isValid()) return false;
    return StringUtil.unquoteString(literal.getText()).equals(property.getKey());
  }

  private static String formatI18nProperty(PsiLiteralExpression literal, IProperty property) {
    return property == null ?
           literal.getText() : "\"" + property.getValue() + "\"";
  }

  @Override
  public boolean isCollapsedByDefault(@NotNull ASTNode node) {
    return isFoldingsOn();
  }


  public static boolean isI18nProperty(@NotNull Project project, @NotNull PsiLiteralExpression expr) {
    if (! isStringLiteral(expr)) return false;
    final IProperty property = expr.getUserData(CACHE);
    if (property == NULL) return false;
    if (property != null) return true;

    final Map<String, Object> annotationParams = new HashMap<String, Object>();
    annotationParams.put(AnnotationUtil.PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER, null);
    final boolean isI18n = JavaI18nUtil.mustBePropertyKey(project, expr, annotationParams);
    if (!isI18n) {
      expr.putUserData(CACHE, NULL);
    }
    return isI18n;
  }

  private static boolean isStringLiteral(PsiLiteralExpression expr) {
    final String text;
    if (expr == null || (text = expr.getText()) == null) return false;
    return text.startsWith("\"") && text.endsWith("\"") && text.length() > 2;
  }
}
