/*
 * 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.convertToJava;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NullUtils;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;

import java.util.Arrays;

/**
 * @author Maxim.Medvedev
 */
class ArgumentListGenerator {
  private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.convertToJava.ArgumentListGenerator");

  private final StringBuilder myBuilder;
  private final ExpressionGenerator myExpressionGenerator;


  public ArgumentListGenerator(StringBuilder builder, ExpressionContext context) {
    myBuilder = builder;
    myExpressionGenerator = new ExpressionGenerator(builder, context);
  }

  public void generate(@Nullable GrClosureSignature signature,
                       @NotNull GrExpression[] exprs,
                       @NotNull GrNamedArgument[] namedArgs,
                       @NotNull GrClosableBlock[] clArgs,
                       @NotNull GroovyPsiElement context) {
    GrClosureSignatureUtil.ArgInfo<PsiElement>[] argInfos =
      signature == null ? null : GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, clArgs, context, false, false);

    if (argInfos == null && signature != null) {
      argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, clArgs, context, true, true);
    }

    final PsiSubstitutor substitutor = signature == null ? PsiSubstitutor.EMPTY : signature.getSubstitutor();
    if (argInfos == null || NullUtils.hasNull(argInfos)) {
      generateSimple(exprs, namedArgs, clArgs, context, substitutor);
      return;
    }

    final GrClosureParameter[] params = signature.getParameters();

    final Project project = context.getProject();
    myBuilder.append('(');
    boolean hasCommaAtEnd = false;
    for (int i = 0; i < argInfos.length; i++) {
      GrClosureSignatureUtil.ArgInfo<PsiElement> arg = argInfos[i];
      if (arg == null) continue;
      final GrClosureParameter param = params[i];
      boolean generated = arg.isMultiArg ? generateMultiArg(arg, param, substitutor, project, context) : generateSingeArg(arg, param);
      if (generated) {
        hasCommaAtEnd = true;
        myBuilder.append(", ");
      }
    }

    if (hasCommaAtEnd) {
      myBuilder.delete(myBuilder.length() - 2, myBuilder.length());
      //myBuilder.removeFromTheEnd(2);
    }

    myBuilder.append(')');
  }

  private boolean generateSingeArg(GrClosureSignatureUtil.ArgInfo<PsiElement> arg, GrClosureParameter param) {
    boolean argExists = !arg.args.isEmpty() && arg.args.get(0) != null;
    if (argExists) {
      final PsiElement actual = arg.args.get(0);
      LOG.assertTrue(actual instanceof GrExpression);
      final PsiType type = param.getType();
      final PsiType declaredType = GenerationUtil.getDeclaredType((GrExpression)actual, myExpressionGenerator.getContext());
      if (type != null && declaredType != null && !TypesUtil.isAssignableByMethodCallConversion(type, declaredType,(GrExpression)actual
      )) {
        myBuilder.append('(');
        TypeWriter.writeType(myBuilder, type, actual);
        myBuilder.append(')');
      }
      ((GrExpression)actual).accept(myExpressionGenerator);
      return true;
    }
    else {
      /*final GrExpression initializer = param.getInitializerGroovy();
      if (initializer != null) {
        initializer.accept(myExpressionGenerator);
      }
      else {
        myBuilder.append("???"); //todo add something more consistent
      }*/
      return false;
    }
  }

  private boolean generateMultiArg(GrClosureSignatureUtil.ArgInfo<PsiElement> arg,
                                   GrClosureParameter param,
                                   PsiSubstitutor substitutor,
                                   Project project,
                                   GroovyPsiElement context) {
    final PsiType type = param.getType();
    //todo find out if param is array in case of it has declared type

    if (type instanceof PsiEllipsisType) {
      for (PsiElement element : arg.args) {
        LOG.assertTrue(element instanceof GrExpression);
        ((GrExpression)element).accept(myExpressionGenerator);
        myBuilder.append(", ");
      }
      if (!arg.args.isEmpty()) {
        myBuilder.delete(myBuilder.length() - 2, myBuilder.length());
        return true;
      }
      else {
        return false;
      }
    }
    else if (type instanceof PsiArrayType) {
      myBuilder.append("new ");
      if (arg.args.isEmpty()) {
        TypeWriter.writeType(myBuilder, ((PsiArrayType)type).getComponentType(), context);
        myBuilder.append("[0]");
      }
      else {
        TypeWriter.writeTypeForNew(myBuilder, type, context);
        myBuilder.append("{");

        for (PsiElement element : arg.args) {
          LOG.assertTrue(element instanceof GrExpression);
          ((GrExpression)element).accept(myExpressionGenerator);
          myBuilder.append(", ");
        }
        if (!arg.args.isEmpty()) myBuilder.delete(myBuilder.length() - 2, myBuilder.length());
        //if (arg.args.size() > 0) myBuilder.removeFromTheEnd(2);
        myBuilder.append('}');
      }
    }
    else {
      final GrExpression listOrMap = GroovyRefactoringUtil.generateArgFromMultiArg(substitutor, arg.args, type, project);
      LOG.assertTrue(listOrMap instanceof GrListOrMap);
      listOrMap.accept(myExpressionGenerator);
    }
    return true;
  }

  private void generateSimple(GrExpression[] exprs,
                              GrNamedArgument[] namedArgs,
                              GrClosableBlock[] closures,
                              GroovyPsiElement context,
                              PsiSubstitutor substitutor) {
    myBuilder.append('(');
    if (namedArgs.length > 0) {
      final GrExpression listOrMap =
        GroovyRefactoringUtil.generateArgFromMultiArg(substitutor, Arrays.asList(namedArgs), null, context.getProject());
      LOG.assertTrue(listOrMap instanceof GrListOrMap);
      listOrMap.accept(myExpressionGenerator);
      myBuilder.append(", ");
    }

    for (GrExpression expr : exprs) {
      expr.accept(myExpressionGenerator);
      myBuilder.append(", ");
    }

    for (GrClosableBlock closure : closures) {
      closure.accept(myExpressionGenerator);
      myBuilder.append(", ");
    }

    if (namedArgs.length + exprs.length + closures.length > 0) {
      myBuilder.delete(myBuilder.length()-2, myBuilder.length());
      //myBuilder.removeFromTheEnd(2);
    }

    myBuilder.append(')');
  }
}
