package com.intellij.structuralsearch.plugin.replace.impl;

import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.structuralsearch.*;
import com.intellij.structuralsearch.impl.matcher.MatcherImplUtil;
import com.intellij.structuralsearch.impl.matcher.PatternTreeContext;
import com.intellij.structuralsearch.impl.matcher.predicates.ScriptSupport;
import com.intellij.structuralsearch.plugin.replace.ReplaceOptions;
import com.intellij.structuralsearch.plugin.replace.ReplacementInfo;
import com.intellij.structuralsearch.plugin.util.CollectingMatchResultSink;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author Maxim.Mossienko
 * Date: Mar 4, 2004
 * Time: 9:19:34 PM
 */
public class Replacer {
  private final Project project;
  private ReplacementBuilder replacementBuilder;
  private ReplaceOptions options;
  private ReplacementContext context;
  private StructuralReplaceHandler replaceHandler;

  public Replacer(Project project, ReplaceOptions options) {
    this.project = project;
    this.options = options;
  }

  public static String stripTypedVariableDecoration(final String type) {
   return type.substring(1,type.length()-1);
 }

  public static int insertSubstitution(StringBuilder result, int offset, final ParameterInfo info, String image) {
   if (image.length() > 0) result.insert(offset+ info.getStartIndex(),image);
   offset += image.length();
   return offset;
 }

  public String testReplace(String in, String what, String by, ReplaceOptions options) throws IncorrectOperationException {
    return testReplace(in, what, by, options,false);
  }

  public String testReplace(String in, String what, String by, ReplaceOptions options, boolean filePattern) {
    FileType type = options.getMatchOptions().getFileType();
    return testReplace(in, what, by, options, filePattern, false, type, null);
  }

  public String testReplace(String in, String what, String by, ReplaceOptions options, boolean filePattern, boolean createPhysicalFile,
                            FileType sourceFileType, Language sourceDialect) {
    this.options = options;
    this.options.getMatchOptions().setSearchPattern(what);
    this.options.setReplacement(by);
    replacementBuilder=null;
    context = null;
    replaceHandler = null;

    this.options.getMatchOptions().clearVariableConstraints();
    MatcherImplUtil.transform(this.options.getMatchOptions());

    checkSupportedReplacementPattern(project, options);

    Matcher matcher = new Matcher(project);
    try {
      PsiElement firstElement, lastElement, parent;

      if (options.getMatchOptions().getScope() == null) {
        PsiElement[] elements = MatcherImplUtil.createTreeFromText(
          in,
          filePattern ? PatternTreeContext.File : PatternTreeContext.Block,
          sourceFileType, sourceDialect, null,
          project,
          createPhysicalFile
        );

        firstElement = elements[0];
        lastElement = elements[elements.length-1];
        parent = firstElement.getParent();

        this.options.getMatchOptions().setScope(
          new LocalSearchScope(parent)
        );
      } else {
        parent = ((LocalSearchScope)options.getMatchOptions().getScope()).getScope()[0];
        firstElement = parent.getFirstChild();
        lastElement = parent.getLastChild();
      }

      this.options.getMatchOptions().setResultIsContextMatch(true);
      CollectingMatchResultSink sink = new CollectingMatchResultSink();
      matcher.testFindMatches(sink, this.options.getMatchOptions());

      final List<ReplacementInfo> resultPtrList = new ArrayList<ReplacementInfo>();

      for (final MatchResult result : sink.getMatches()) {
        resultPtrList.add(buildReplacement(result));
      }

      sink.getMatches().clear();

      int startOffset = firstElement.getTextRange().getStartOffset();
      int endOffset = filePattern ?0: parent.getTextLength() - (lastElement.getTextRange().getEndOffset());

      // get nodes from text may contain
      PsiElement prevSibling = firstElement.getPrevSibling();
      if (prevSibling instanceof PsiWhiteSpace) {
        startOffset -= prevSibling.getTextLength() - 1;
      }

      PsiElement nextSibling = lastElement.getNextSibling();
      if (nextSibling instanceof PsiWhiteSpace) {
        endOffset -= nextSibling.getTextLength() - 1;
      }

      replaceAll(resultPtrList);

      String result = parent.getText();
      result = result.substring(startOffset);
      result = result.substring(0,result.length() - endOffset);

      return result;
    }
    catch (Exception e) {
      throw new IncorrectOperationException(e);
    }
    finally {
      options.getMatchOptions().setScope(null);
    }
  }

  public void replaceAll(final List<ReplacementInfo> resultPtrList) {
    PsiElement lastAffectedElement = null;
    PsiElement currentAffectedElement;

    for (ReplacementInfo info : resultPtrList) {
      PsiElement element = info.getMatch(0);
      initContextAndHandler(element);
      if (replaceHandler != null) {
        replaceHandler.prepare(info);
      }
    }

    for (final ReplacementInfo aResultPtrList : resultPtrList) {
      currentAffectedElement = doReplace(aResultPtrList);

      if (currentAffectedElement != lastAffectedElement) {
        if (lastAffectedElement != null) reformatAndPostProcess(lastAffectedElement);
        lastAffectedElement = currentAffectedElement;
      }
    }

    reformatAndPostProcess(lastAffectedElement);
  }

  public void replace(ReplacementInfo info) {
    PsiElement element = info.getMatch(0);
    initContextAndHandler(element);

    if (replaceHandler != null) {
      replaceHandler.prepare(info);
    }
    reformatAndPostProcess(doReplace(info));
  }

  @Nullable
  private PsiElement doReplace(final ReplacementInfo info) {
    final ReplacementInfoImpl replacementInfo = (ReplacementInfoImpl)info;
    final PsiElement element = replacementInfo.matchesPtrList.get(0).getElement();

    if (element==null || !element.isWritable() || !element.isValid()) return null;

    final PsiElement elementParent = element.getParent();

    //noinspection HardCodedStringLiteral
    CommandProcessor.getInstance().executeCommand(
      project,
      new Runnable() {
        public void run() {
          ApplicationManager.getApplication().runWriteAction(
            new Runnable() {
              public void run() {
                doReplace(element, replacementInfo);
              }
            }
          );
          PsiDocumentManager.getInstance(project).commitAllDocuments();
        }
      },
      "ssreplace",
      "test"
    );

    if (!elementParent.isValid() || !elementParent.isWritable()) {
      return null;
    }

    return elementParent;
  }

  private void reformatAndPostProcess(final PsiElement elementParent) {
    if (elementParent == null) return;
    final Runnable action = new Runnable() {
      public void run() {
        final PsiFile containingFile = elementParent.getContainingFile();

        if (containingFile != null && options.isToReformatAccordingToStyle()) {
          if (containingFile.getVirtualFile() != null) {
            PsiDocumentManager.getInstance(project)
              .commitDocument(FileDocumentManager.getInstance().getDocument(containingFile.getVirtualFile()));
          }

          final int parentOffset = elementParent.getTextRange().getStartOffset();
          CodeStyleManager.getInstance(project)
            .reformatRange(containingFile, parentOffset, parentOffset + elementParent.getTextLength(), true);
        }
        if (replaceHandler != null) {
          replaceHandler.postProcess(elementParent, options);
        }
      }
    };

    CommandProcessor.getInstance().executeCommand(
      project,
      new Runnable() {
        public void run() {
          ApplicationManager.getApplication().runWriteAction(action);
        }
      },
      "reformat and shorten refs after ssr",
      "test"
    );
  }

  private void doReplace(final PsiElement elementToReplace,
                         final ReplacementInfoImpl info) {
    CodeStyleManager.getInstance(project).performActionWithFormatterDisabled(new Runnable() {
        public void run() {
          initContextAndHandler(elementToReplace);

          context.replacementInfo = info;

          if (replaceHandler != null) {
            replaceHandler.replace(info, options);
          }
        }
      }
    );
  }

  private void initContextAndHandler(PsiElement psiContext) {
    if (context == null) {
      context = new ReplacementContext(options, project);
    }
    if (replaceHandler == null) {
      StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(psiContext);
      if (profile != null) {
        replaceHandler = profile.getReplaceHandler(this.context);
      }
    }
  }

  public static void handleComments(final PsiElement el, final PsiElement replacement, ReplacementContext context) throws IncorrectOperationException {
    ReplacementInfoImpl replacementInfo = context.replacementInfo;
    if (replacementInfo.elementToVariableNameMap == null) {
      replacementInfo.elementToVariableNameMap = new HashMap<PsiElement, String>(1);
      Map<String, MatchResult> variableMap = replacementInfo.variableMap;
      if (variableMap != null) {
        for(String name:variableMap.keySet()) {
          fill(name,replacementInfo.variableMap.get(name),replacementInfo.elementToVariableNameMap);
        }
      }
    }

    PsiElement lastChild = el.getLastChild();
    if (lastChild instanceof PsiComment &&
        replacementInfo.elementToVariableNameMap.get(lastChild) == null &&
        !(replacement.getLastChild() instanceof PsiComment)
      ) {
      PsiElement firstElementAfterStatementEnd = lastChild;
      for(PsiElement curElement=firstElementAfterStatementEnd.getPrevSibling();curElement!=null;curElement = curElement.getPrevSibling()) {
        if (!(curElement instanceof PsiWhiteSpace) && !(curElement instanceof PsiComment)) break;
        firstElementAfterStatementEnd = curElement;
      }
      replacement.addRangeAfter(firstElementAfterStatementEnd,lastChild,replacement.getLastChild());
    }

    final PsiElement firstChild = el.getFirstChild();
    if (firstChild instanceof PsiComment &&
        !(firstChild instanceof PsiDocCommentBase) &&
        replacementInfo.elementToVariableNameMap.get(firstChild) == null
        ) {
      PsiElement lastElementBeforeStatementStart = firstChild;

      for(PsiElement curElement=lastElementBeforeStatementStart.getNextSibling();curElement!=null;curElement = curElement.getNextSibling()) {
        if (!(curElement instanceof PsiWhiteSpace) && !(curElement instanceof PsiComment)) break;
        lastElementBeforeStatementStart = curElement;
      }
      replacement.addRangeBefore(firstChild,lastElementBeforeStatementStart,replacement.getFirstChild());
    }
  }

  private static void fill(final String name, final MatchResult matchResult, final Map<PsiElement, String> elementToVariableNameMap) {
    boolean b = matchResult.isMultipleMatch() || matchResult.isScopeMatch();
    if(matchResult.hasSons() && b) {
      for(MatchResult r:matchResult.getAllSons()) {
        fill(name, r, elementToVariableNameMap);
      }
    } else if (!b && matchResult.getMatchRef() != null)  {
      elementToVariableNameMap.put(matchResult.getMatch(),name);
    }
  }

  public static void checkSupportedReplacementPattern(Project project, ReplaceOptions options) throws UnsupportedPatternException {
    try {
      String search = options.getMatchOptions().getSearchPattern();
      String replacement = options.getReplacement();
      FileType fileType = options.getMatchOptions().getFileType();
      Template template = TemplateManager.getInstance(project).createTemplate("","",search);
      Template template2 = TemplateManager.getInstance(project).createTemplate("","",replacement);

      int segmentCount = template2.getSegmentsCount();
      for(int i=0;i<segmentCount;++i) {
        final String replacementSegmentName = template2.getSegmentName(i);
        final int segmentCount2  = template.getSegmentsCount();
        int j;

        for(j=0;j<segmentCount2;++j) {
          final String searchSegmentName = template.getSegmentName(j);

          if (replacementSegmentName.equals(searchSegmentName)) break;

          // Reference to
          if (replacementSegmentName.startsWith(searchSegmentName) &&
              replacementSegmentName.charAt(searchSegmentName.length())=='_'
             ) {
            try {
              Integer.parseInt(replacementSegmentName.substring(searchSegmentName.length()+1));
              break;
            } catch(NumberFormatException ex) {}
          }
        }

        if (j==segmentCount2) {
          ReplacementVariableDefinition definition = options.getVariableDefinition(replacementSegmentName);

          if (definition == null || definition.getScriptCodeConstraint().length() <= 2 /*empty quotes*/) {
            throw new UnsupportedPatternException(
              SSRBundle.message("replacement.variable.is.not.defined.message", replacementSegmentName)
            );
          } else {
            String message = ScriptSupport.checkValidScript(StringUtil.stripQuotesAroundValue(definition.getScriptCodeConstraint()));
            if (message != null) {
              throw new UnsupportedPatternException(
                SSRBundle.message("replacement.variable.is.not.valid", replacementSegmentName, message)
              );
            }
          }
        }
      }

      StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType);

      profile.checkReplacementPattern(project, options);

    } catch(IncorrectOperationException ex) {
      throw new UnsupportedPatternException(SSRBundle.message("incorrect.pattern.message"));
    }
  }

  public ReplacementInfo buildReplacement(MatchResult result) {
    List<SmartPsiElementPointer> l = new ArrayList<SmartPsiElementPointer>();
    SmartPointerManager manager = SmartPointerManager.getInstance(project);

    if (MatchResult.MULTI_LINE_MATCH.equals(result.getName())) {
      for(Iterator<MatchResult> i=result.getAllSons().iterator();i.hasNext();) {
        final MatchResult r = i.next();

        if (MatchResult.LINE_MATCH.equals(r.getName())) {
          PsiElement element = r.getMatchRef().getElement();

          if (element instanceof PsiDocCommentBase) { // doc comment is not collapsed when created in block
            if (i.hasNext()) {
              MatchResult matchResult = i.next();

              if (MatchResult.LINE_MATCH.equals(matchResult.getName()) &&
                  StructuralSearchUtil.isDocCommentOwner(matchResult.getMatch())) {
                element = matchResult.getMatch();
              } else {
                l.add( manager.createSmartPsiElementPointer(element) );
                element = matchResult.getMatch();
              }
            }
          }
          l.add( manager.createSmartPsiElementPointer(element) );
        }
      }
    } else {
      l.add( manager.createSmartPsiElementPointer(result.getMatchRef().getElement()));
    }

    ReplacementInfoImpl replacementInfo = new ReplacementInfoImpl();

    replacementInfo.matchesPtrList = l;
    if (replacementBuilder==null) {
      replacementBuilder = new ReplacementBuilder(project,options);
    }
    replacementInfo.result = replacementBuilder.process(result, replacementInfo, options.getMatchOptions().getFileType());
    replacementInfo.matchResult = result;

    return replacementInfo;
  }
}
