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

/*
 * @author max
 */
package org.jetbrains.generate.tostring;

import com.intellij.codeInsight.hint.HintManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.util.IncorrectOperationException;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.generate.tostring.config.*;
import org.jetbrains.generate.tostring.element.*;
import org.jetbrains.generate.tostring.exception.GenerateCodeException;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import org.jetbrains.generate.tostring.template.TemplateResource;
import org.jetbrains.generate.tostring.velocity.VelocityFactory;
import org.jetbrains.generate.tostring.view.MethodExistsDialog;

import java.io.StringWriter;
import java.util.*;

public class GenerateToStringWorker {
  private static final Logger logger = Logger.getInstance("#org.jetbrains.generate.tostring.GenerateToStringWorker");

  private final Editor editor;
  private final PsiClass clazz;
  private final Config config;
  private final boolean hasOverrideAnnotation;

  public GenerateToStringWorker(PsiClass clazz, Editor editor, boolean insertAtOverride) {
    this.clazz = clazz;
    this.editor = editor;
    this.config = GenerateToStringContext.getConfig();
    this.hasOverrideAnnotation = insertAtOverride;
  }

  public void execute(Collection<PsiMember> members, TemplateResource template) throws IncorrectOperationException, GenerateCodeException {
    // decide what to do if the method already exists
    ConflictResolutionPolicy resolutionPolicy = exitsMethodDialog(template);
    // what insert policy should we use?
    resolutionPolicy.setNewMethodStrategy(getStrategy(config.getInsertNewMethodInitialOption()));

    // user didn't click cancel so go on
    Map<String, String> params = new HashMap<String, String>();

    // before
    beforeCreateToStringMethod(params, template);

    // generate method
    PsiMethod method = createToStringMethod(members, resolutionPolicy, params, template);

    // after, if method was generated (not cancel policy)
    if (method != null) {
      afterCreateToStringMethod(method, params, template);
    }
  }

  private static InsertNewMethodStrategy getStrategy(InsertWhere option) {
    switch (option) {
      case AFTER_EQUALS_AND_HASHCODE:
        return InsertAfterEqualsHashCodeStrategy.getInstance();
      case AT_CARET:
        return InsertAtCaretStrategy.getInstance();
      case AT_THE_END_OF_A_CLASS:
        return InsertLastStrategy.getInstance();
    }

    return InsertLastStrategy.getInstance();
  }

  /**
   * This method gets the choice if there is an existing <code>toString</code> method.
   * <br/> 1) If there is a settings to always override use this.
   * <br/> 2) Prompt a dialog and let the user decide.
   *
   * @param template the chosen template to use
   * @return the policy the user selected (never null)
   */
  protected ConflictResolutionPolicy exitsMethodDialog(TemplateResource template) {
    final DuplicationPolicy dupPolicy = config.getReplaceDialogInitialOption();
    if (dupPolicy == DuplicationPolicy.ASK) {
      PsiMethod existingMethod = PsiAdapter.findMethodByName(clazz, template.getTargetMethodName());
      if (existingMethod != null) {
        return MethodExistsDialog.showDialog(template.getTargetMethodName());
      }
    }
    else if (dupPolicy == DuplicationPolicy.REPLACE) {
      return ReplacePolicy.getInstance();
    }

    // If there is no conflict, duplicate policy will do the trick
    return DuplicatePolicy.getInstance();
  }

  /**
   * This method is executed just before the <code>toString</code> method is created or updated.
   *
   * @param params   additional parameters stored with key/value in the map.
   * @param template the template to use
   */
  private void beforeCreateToStringMethod(Map<String, String> params, TemplateResource template) {
    PsiMethod existingMethod = PsiAdapter.findMethodByName(clazz, template.getTargetMethodName()); // find the existing method
    if (existingMethod != null && existingMethod.getDocComment() != null) {
      PsiDocComment doc = existingMethod.getDocComment();
      if (doc != null) {
        params.put("existingJavaDoc", doc.getText());
      }
    }
  }

  /**
   * Creates the <code>toString</code> method.
   *
   * @param selectedMembers the selected members as both {@link com.intellij.psi.PsiField} and {@link com.intellij.psi.PsiMethod}.
   * @param policy          conflict resolution policy
   * @param params          additional parameters stored with key/value in the map.
   * @param template        the template to use
   * @return the created method, null if the method is not created due the user cancels this operation
   * @throws GenerateCodeException       is thrown when there is an error generating the javacode.
   * @throws IncorrectOperationException is thrown by IDEA.
   */
  @Nullable
  private PsiMethod createToStringMethod(Collection<PsiMember> selectedMembers,
                                         ConflictResolutionPolicy policy,
                                         Map<String, String> params,
                                         TemplateResource template) throws IncorrectOperationException, GenerateCodeException {
    // generate code using velocity
    String body = velocityGenerateCode(selectedMembers, params, template.getMethodBody());
    if (logger.isDebugEnabled()) logger.debug("Method body generated from Velocity:\n" + body);

    // fix weird linebreak problem in IDEA #3296 and later
    body = StringUtil.convertLineSeparators(body);

    // create psi newMethod named toString()
    final JVMElementFactory topLevelFactory = JVMElementFactories.getFactory(clazz.getLanguage(), clazz.getProject());
    if (topLevelFactory == null) {
      return null;
    }
    PsiMethod newMethod;
    try {
      newMethod = topLevelFactory.createMethodFromText(template.getMethodSignature() + " { " + body + " }", clazz);
      CodeStyleManager.getInstance(clazz.getProject()).reformat(newMethod);
    } catch (IncorrectOperationException ignore) {
      HintManager.getInstance().showErrorHint(editor, "'toString()' method could not be created from template '" +
                                                      template.getFileName() + '\'');
      return null;
    }

    // insertNewMethod conflict resolution policy (add/replace, duplicate, cancel)
    PsiMethod existingMethod = clazz.findMethodBySignature(newMethod, false);
    PsiMethod toStringMethod = policy.applyMethod(clazz, existingMethod, newMethod, editor);
    if (toStringMethod == null) {
      return null; // user cancelled so return null
    }

    if (hasOverrideAnnotation) {
      toStringMethod.getModifierList().addAnnotation("java.lang.Override");
    }

    // applyJavaDoc conflict resolution policy (add or keep existing)
    String existingJavaDoc = params.get("existingJavaDoc");
    String newJavaDoc = template.getJavaDoc();
    if (existingJavaDoc != null || newJavaDoc != null) {
      // generate javadoc using velocity
      newJavaDoc = velocityGenerateCode(selectedMembers, params, newJavaDoc);
      if (logger.isDebugEnabled()) logger.debug("JavaDoc body generated from Velocity:\n" + newJavaDoc);

      applyJavaDoc(toStringMethod, existingJavaDoc, newJavaDoc);
    }

    // return the created method
    return toStringMethod;
  }

  private static void applyJavaDoc(PsiMethod newMethod, String existingJavaDoc, String newJavaDoc) {
    String text = newJavaDoc != null ? newJavaDoc : existingJavaDoc; // prefer to use new javadoc
    PsiAdapter.addOrReplaceJavadoc(newMethod, text, true);
  }


  /**
   * This method is executed just after the <code>toString</code> method is created or updated.
   *
   * @param method   the newly created/updated <code>toString</code> method.
   * @param params   additional parameters stored with key/value in the map.
   * @param template the template to use
   * @throws IncorrectOperationException is thrown by IDEA
   */
  private void afterCreateToStringMethod(PsiMethod method, Map<String, String> params, TemplateResource template) {
    PsiFile containingFile = clazz.getContainingFile();
    if (containingFile instanceof PsiJavaFile) {
      final PsiJavaFile javaFile = (PsiJavaFile)containingFile;
      if (params.get("autoImportPackages") != null) {
        // keep this for old user templates
        autoImportPackages(javaFile, params.get("autoImportPackages"));
      }
    }
    method = (PsiMethod)JavaCodeStyleManager.getInstance(clazz.getProject()).shortenClassReferences(method);

    // jump to method
    if (!config.isJumpToMethod() || editor == null) {
      return;
    }
    int offset = method.getTextOffset();
    if (offset <= 2) {
      return;
    }
    VisualPosition vp = editor.offsetToVisualPosition(offset);
    if (logger.isDebugEnabled()) logger.debug("Moving/Scrolling caret to " + vp + " (offset=" + offset + ")");
    editor.getCaretModel().moveToVisualPosition(vp);
    editor.getScrollingModel().scrollToCaret(ScrollType.CENTER_DOWN);
  }

  /**
   * Automatic import the packages.
   *
   * @param packageNames names of packages (must end with .* and be separated by ; or ,)
   * @throws IncorrectOperationException error adding imported package
   */
  private static void autoImportPackages(PsiJavaFile psiJavaFile, String packageNames) throws IncorrectOperationException {
    StringTokenizer tok = new StringTokenizer(packageNames, ",");
    while (tok.hasMoreTokens()) {
      String packageName = tok.nextToken().trim(); // trim in case of space
      if (logger.isDebugEnabled()) logger.debug("Auto importing package: " + packageName);
      PsiAdapter.addImportStatement(psiJavaFile, packageName);
    }
  }

  /**
   * Generates the code using Velocity.
   * <p/>
   * This is used to create the <code>toString</code> method body and it's javadoc.
   *
   * @param selectedMembers the selected members as both {@link com.intellij.psi.PsiField} and {@link com.intellij.psi.PsiMethod}.
   * @param params          additional parameters stored with key/value in the map.
   * @param templateMacro   the velocity macro template
   * @return code (usually javacode). Returns null if templateMacro is null.
   * @throws GenerateCodeException is thrown when there is an error generating the javacode.
   */
  private String velocityGenerateCode(Collection<PsiMember> selectedMembers, Map<String, String> params, String templateMacro)
    throws GenerateCodeException {
    if (templateMacro == null) {
      return null;
    }

    StringWriter sw = new StringWriter();
    try {
      VelocityContext vc = new VelocityContext();

      vc.put("java_version", PsiAdapter.getJavaVersion(clazz));

      // field information
      logger.debug("Velocity Context - adding fields");
      vc.put("fields", ElementUtils.getOnlyAsFieldElements(selectedMembers));

      // method information
      logger.debug("Velocity Context - adding methods");
      vc.put("methods", ElementUtils.getOnlyAsMethodElements(selectedMembers));

      // element information (both fields and methods)
      logger.debug("Velocity Context - adding members (fields and methods)");
      List<Element> elements = ElementUtils.getOnlyAsFieldAndMethodElements(selectedMembers);
      // sort elements if enabled and not using chooser dialog
      if (config.getSortElements() != 0) {
        Collections.sort(elements, new ElementComparator(config.getSortElements()));
      }
      vc.put("members", elements);

      // class information
      ClassElement ce = ElementFactory.newClassElement(clazz);
      vc.put("class", ce);
      if (logger.isDebugEnabled()) logger.debug("Velocity Context - adding class: " + ce);

      // information to keep as it is to avoid breaking compatibility with prior releases
      vc.put("classname", config.isUseFullyQualifiedName() ? ce.getQualifiedName() : ce.getName());
      vc.put("FQClassname", ce.getQualifiedName());

      if (logger.isDebugEnabled()) logger.debug("Velocity Macro:\n" + templateMacro);

      // velocity
      VelocityEngine velocity = VelocityFactory.getVelocityEngine();
      logger.debug("Executing velocity +++ START +++");
      velocity.evaluate(vc, sw, this.getClass().getName(), templateMacro);
      logger.debug("Executing velocity +++ END +++");

      // any additional packages to import returned from velocity?
      if (vc.get("autoImportPackages") != null) {
        params.put("autoImportPackages", (String)vc.get("autoImportPackages"));
      }
    }
    catch (Exception e) {
      throw new GenerateCodeException("Error in Velocity code generator", e);
    }

    return sw.getBuffer().toString();
  }

  /**
   * Generates the toString() code for the specified class and selected
   * fields, doing the work through a WriteAction ran by a CommandProcessor.
   *
   * @param selectedMembers list of members selected
   * @param template         the chosen template to use
   * @param insertAtOverride
   */
  public static void executeGenerateActionLater(final PsiClass clazz,
                                                final Editor editor,
                                                final Collection<PsiMember> selectedMembers,
                                                final TemplateResource template,
                                                final boolean insertAtOverride) {
    Runnable writeCommand = new Runnable() {
      public void run() {
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
          public void run() {
            try {
              new GenerateToStringWorker(clazz, editor, insertAtOverride).execute(selectedMembers, template);
            }
            catch (Exception e) {
              GenerateToStringUtils.handleException(clazz.getProject(), e);
            }
          }
        });
      }
    };

    CommandProcessor.getInstance().executeCommand(clazz.getProject(), writeCommand, "GenerateToString", null);
  }
}
