/*
 * 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 com.intellij.openapi.vcs.checkin;

import com.intellij.ide.todo.TodoFilter;
import com.intellij.ide.todo.TodoIndexPatternProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.ex.DiffFragment;
import com.intellij.openapi.diff.impl.ComparisonPolicy;
import com.intellij.openapi.diff.impl.fragments.LineFragment;
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
import com.intellij.openapi.diff.impl.processing.DiffCorrection;
import com.intellij.openapi.diff.impl.processing.DiffFragmentsProcessor;
import com.intellij.openapi.diff.impl.processing.DiffPolicy;
import com.intellij.openapi.diff.impl.string.DiffString;
import com.intellij.openapi.diff.impl.util.TextDiffTypeEnum;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.search.LightIndexPatternSearch;
import com.intellij.psi.impl.search.TodoItemsCreator;
import com.intellij.psi.search.IndexPatternOccurrence;
import com.intellij.psi.search.PsiTodoSearchHelper;
import com.intellij.psi.search.TodoItem;
import com.intellij.psi.search.searches.IndexPatternSearch;
import com.intellij.util.PairConsumer;
import com.intellij.util.SmartList;
import com.intellij.util.containers.Convertor;
import com.intellij.util.diff.FilesTooBigForDiffException;

import java.util.*;

/**
 * @author irengrig
 *         Date: 2/18/11
 *         Time: 5:16 PM
 */
public class TodoCheckinHandlerWorker {
  private final static Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.checkin.TodoCheckinHandler");

  private final Collection<Change> changes;
  private final TodoFilter myTodoFilter;
  private final boolean myIncludePattern;
  private final PsiManager myPsiManager;
  private final PsiTodoSearchHelper mySearchHelper;

  private final List<TodoItem> myAddedOrEditedTodos;
  private final List<TodoItem> myInChangedTodos;
  private final List<Pair<FilePath, String>> mySkipped;
  private PsiFile myPsiFile;
  private List<TodoItem> myNewTodoItems;
  private final MyEditedFileProcessor myEditedFileProcessor;


  public TodoCheckinHandlerWorker(final Project project, final Collection<Change> changes, final TodoFilter todoFilter,
                                  final boolean includePattern) {
    this.changes = changes;
    myTodoFilter = todoFilter;
    myIncludePattern = includePattern;
    myPsiManager = PsiManager.getInstance(project);
    mySearchHelper = PsiTodoSearchHelper.SERVICE.getInstance(project);
    myAddedOrEditedTodos = new ArrayList<TodoItem>();
    myInChangedTodos = new ArrayList<TodoItem>();
    mySkipped = new SmartList<Pair<FilePath,String>>();
    myEditedFileProcessor = new MyEditedFileProcessor(project, new Acceptor() {
      @Override
      public void skipped(Pair<FilePath, String> pair) {
        mySkipped.add(pair);
      }

      @Override
      public void addedOrEdited(TodoItem todoItem) {
        myAddedOrEditedTodos.add(todoItem);
      }

      @Override
      public void inChanged(TodoItem todoItem) {
        myInChangedTodos.add(todoItem);
      }
    }, myTodoFilter);
  }

  public void execute() {
    for (Change change : changes) {
      ProgressManager.checkCanceled();
      if (change.getAfterRevision() == null) continue;
      VirtualFile afterFile = change.getAfterRevision().getFile().getVirtualFile();
      if (afterFile == null) {
        afterFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(change.getAfterRevision().getFile().getIOFile());
      }
      if (afterFile == null || afterFile.isDirectory() || afterFile.getFileType().isBinary()) continue;
      myPsiFile = null;

      if (afterFile.isValid()) {
        myPsiFile = myPsiManager.findFile(afterFile);
      }
      if (myPsiFile == null) {
        mySkipped.add(Pair.create(change.getAfterRevision().getFile(), ourInvalidFile));
        continue;
      }

      myNewTodoItems = new ArrayList<TodoItem>(Arrays.asList(mySearchHelper.findTodoItems(myPsiFile)));
      applyFilterAndRemoveDuplicates(myNewTodoItems, myTodoFilter);
      if (change.getBeforeRevision() == null) {
        // take just all todos
        if (myNewTodoItems.isEmpty()) continue;
        myAddedOrEditedTodos.addAll(myNewTodoItems);
      }
      else {
        myEditedFileProcessor.process(change, myNewTodoItems);
      }
    }
  }

  private static void applyFilterAndRemoveDuplicates(final List<TodoItem> todoItems, final TodoFilter filter) {
    TodoItem previous = null;
    for (Iterator<TodoItem> iterator = todoItems.iterator(); iterator.hasNext(); ) {
      final TodoItem next = iterator.next();
      if (filter != null && ! filter.contains(next.getPattern())) {
        iterator.remove();
        continue;
      }
      if (previous != null && next.getTextRange().equals(previous.getTextRange())) {
        iterator.remove();
      } else {
        previous = next;
      }
    }
  }

  private static class MyEditedFileProcessor {
    //private String myFileText;
    private String myBeforeContent;
    private String myAfterContent;
    private List<TodoItem> myOldItems;
    private LineFragment myCurrentLineFragment;
    private HashSet<String> myOldTodoTexts;
    private PsiFile myBeforeFile;
    private final PsiFileFactory myPsiFileFactory;
    private FilePath myAfterFile;
    private final Acceptor myAcceptor;
    private final TodoFilter myTodoFilter;

    private MyEditedFileProcessor(final Project project, Acceptor acceptor, final TodoFilter todoFilter) {
      myAcceptor = acceptor;
      myTodoFilter = todoFilter;
      myPsiFileFactory = PsiFileFactory.getInstance(project);
    }

    public void process(final Change change, final List<TodoItem> newTodoItems) {
      myBeforeFile = null;
      //myFileText = null;
      myOldItems = null;
      myOldTodoTexts = null;

      myAfterFile = change.getAfterRevision().getFile();
      try {
        myBeforeContent = change.getBeforeRevision().getContent();
        myAfterContent = change.getAfterRevision().getContent();
        if (myAfterContent == null) {
          myAcceptor.skipped(Pair.create(myAfterFile, ourCannotLoadCurrentRevision));
          return;
        }
        if (myBeforeContent == null) {
          myAcceptor.skipped(Pair.create(myAfterFile, ourCannotLoadPreviousRevision));
          return;
        }
        ArrayList<LineFragment> lineFragments = getLineFragments(myAfterFile.getPath(), myBeforeContent, myAfterContent);
        for (Iterator<LineFragment> iterator = lineFragments.iterator(); iterator.hasNext(); ) {
          ProgressManager.checkCanceled();
          final LineFragment next = iterator.next();
          final TextDiffTypeEnum type = next.getType();
          assert ! TextDiffTypeEnum.CONFLICT.equals(type);
          if (type == null || TextDiffTypeEnum.DELETED.equals(type) || TextDiffTypeEnum.NONE.equals(type)) {
            iterator.remove();
          }
        }
        final StepIntersection<TodoItem, LineFragment> intersection =
          new StepIntersection<TodoItem, LineFragment>(TodoItemConvertor.getInstance(), LineFragmentConvertor.getInstance(), lineFragments,
                                                       new Getter<String>() {
                                                         @Override
                                                         public String get() {
                                                           return myAfterContent;
                                                         }
                                                       });

        intersection.process(newTodoItems, new PairConsumer<TodoItem, LineFragment>() {

          @Override
          public void consume(TodoItem todoItem, LineFragment lineFragment) {
            ProgressManager.checkCanceled();
            if (myCurrentLineFragment == null || ! myCurrentLineFragment.getRange(FragmentSide.SIDE2).equals(
              lineFragment.getRange(FragmentSide.SIDE2))) {
              myCurrentLineFragment = lineFragment;
              myOldTodoTexts = null;
            }
            final TextDiffTypeEnum type = lineFragment.getType();
            if (TextDiffTypeEnum.INSERT.equals(type)) {
              myAcceptor.addedOrEdited(todoItem);
            } else {
              // change
              checkEditedFragment(todoItem);
            }
          }
        });
      } catch (VcsException e) {
        LOG.info(e);
        myAcceptor.skipped(Pair.create(myAfterFile, ourCannotLoadPreviousRevision));
      }
    }

    private void checkEditedFragment(TodoItem newTodoItem) {
      if (myBeforeFile == null) {
        myBeforeFile = myPsiFileFactory.createFileFromText("old" + myAfterFile.getName(), myAfterFile.getFileType(), myBeforeContent);
      }
      if (myOldItems == null)  {
        final Collection<IndexPatternOccurrence> all =
          LightIndexPatternSearch.SEARCH.createQuery(new IndexPatternSearch.SearchParameters(myBeforeFile, TodoIndexPatternProvider
            .getInstance())).findAll();

        final TodoItemsCreator todoItemsCreator = new TodoItemsCreator();
        myOldItems = new ArrayList<TodoItem>();
        if (all.isEmpty()) {
          myAcceptor.addedOrEdited(newTodoItem);
          return;
        }
        for (IndexPatternOccurrence occurrence : all) {
          myOldItems.add(todoItemsCreator.createTodo(occurrence));
        }
        applyFilterAndRemoveDuplicates(myOldItems, myTodoFilter);
      }
      if (myOldTodoTexts == null) {
        final StepIntersection<LineFragment, TodoItem> intersection = new StepIntersection<LineFragment, TodoItem>(
          LineFragmentConvertor.getInstance(), TodoItemConvertor.getInstance(), myOldItems, new Getter<String>() {
          @Override
          public String get() {
            return myBeforeContent;
          }
        });
        myOldTodoTexts = new HashSet<String>();
        intersection.process(Collections.singletonList(myCurrentLineFragment), new PairConsumer<LineFragment, TodoItem>() {
          @Override
          public void consume(LineFragment lineFragment, TodoItem todoItem) {
            myOldTodoTexts.add(getTodoText(todoItem, myBeforeContent));
          }
        });
      }
      final String text = getTodoText(newTodoItem, myAfterContent);
      if (! myOldTodoTexts.contains(text)) {
        myAcceptor.addedOrEdited(newTodoItem);
      } else {
        myAcceptor.inChanged(newTodoItem);
      }
    }
  }

  interface Acceptor {
    void skipped(Pair<FilePath, String> pair);
    void addedOrEdited(final TodoItem todoItem);
    void inChanged(final TodoItem todoItem);
  }

  public List<TodoItem> getAddedOrEditedTodos() {
    return myAddedOrEditedTodos;
  }

  public List<TodoItem> getInChangedTodos() {
    return myInChangedTodos;
  }

  public List<Pair<FilePath, String>> getSkipped() {
    return mySkipped;
  }

  private static String getTodoText(TodoItem oldItem, final String content) {
    final String fragment = content.substring(oldItem.getTextRange().getStartOffset(), oldItem.getTextRange().getEndOffset());
    return StringUtil.join(fragment.split("\\s"), " ");
  }

  private static ArrayList<LineFragment> getLineFragments(final String fileName, String beforeContent, String afterContent) throws VcsException {
    try {
      DiffFragment[] woFormattingBlocks =
        DiffPolicy.LINES_WO_FORMATTING.buildFragments(DiffString.create(beforeContent), DiffString.create(afterContent));
      DiffFragment[] step1lineFragments =
        new DiffCorrection.TrueLineBlocks(ComparisonPolicy.IGNORE_SPACE).correctAndNormalize(woFormattingBlocks);
      return new DiffFragmentsProcessor().process(step1lineFragments);
    } catch (FilesTooBigForDiffException e) {
      throw new VcsException("File " + fileName + " is too big and there are too many changes to build a diff", e);
    }
  }

  private final static String ourInvalidFile = "Invalid file (s)";
  private final static String ourCannotLoadPreviousRevision = "Can not load previous revision";
  private final static String ourCannotLoadCurrentRevision = "Can not load current revision";

  private static class TodoItemConvertor implements Convertor<TodoItem, TextRange> {
    private static final TodoItemConvertor ourInstance = new TodoItemConvertor();

    public static TodoItemConvertor getInstance() {
      return ourInstance;
    }

    @Override
    public TextRange convert(TodoItem o) {
      final TextRange textRange = o.getTextRange();
      return new TextRange(textRange.getStartOffset(), textRange.getEndOffset() - 1);
    }
  }

  private static class LineFragmentConvertor implements Convertor<LineFragment, TextRange> {
    private static final LineFragmentConvertor ourInstance = new LineFragmentConvertor();

    public static LineFragmentConvertor getInstance() {
      return ourInstance;
    }

    @Override
    public TextRange convert(LineFragment o) {
      final TextRange textRange = o.getRange(FragmentSide.SIDE2);
      return new TextRange(textRange.getStartOffset(), textRange.getEndOffset() - 1);
    }
  }

  public List<TodoItem> inOneList() {
    final List<TodoItem> list = new ArrayList<TodoItem>();
    list.addAll(getAddedOrEditedTodos());
    list.addAll(getInChangedTodos());
    return list;
  }
}
