/*
 * Copyright 2000-2009 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.update;

import com.intellij.history.ByteContent;
import com.intellij.history.Label;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.actions.ShowDiffAction;
import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.lang.ref.SoftReference;
import java.util.Iterator;

public class ShowUpdatedDiffAction extends AnAction implements DumbAware {
  @Override
  public void update(AnActionEvent e) {
    final DataContext dc = e.getDataContext();

    final Presentation presentation = e.getPresentation();

    //presentation.setVisible(isVisible(dc));
    presentation.setEnabled(isVisible(dc) && isEnabled(dc));
  }

  private boolean isVisible(final DataContext dc) {
    final Project project = CommonDataKeys.PROJECT.getData(dc);
    return (project != null) && (VcsDataKeys.LABEL_BEFORE.getData(dc) != null) && (VcsDataKeys.LABEL_AFTER.getData(dc) != null);
  }

  private boolean isEnabled(final DataContext dc) {
    final Iterable<Pair<VirtualFilePointer,FileStatus>> iterable = VcsDataKeys.UPDATE_VIEW_FILES_ITERABLE.getData(dc);
    return iterable != null;
  }

  public void actionPerformed(AnActionEvent e) {
    final DataContext dc = e.getDataContext();
    if ((! isVisible(dc)) || (! isEnabled(dc))) return;

    final Project project = CommonDataKeys.PROJECT.getData(dc);
    final Iterable<Pair<VirtualFilePointer, FileStatus>> iterable = VcsDataKeys.UPDATE_VIEW_FILES_ITERABLE.getData(dc);
    final Label before = (Label) VcsDataKeys.LABEL_BEFORE.getData(dc);
    final Label after = (Label) VcsDataKeys.LABEL_AFTER.getData(dc);

    final String selectedUrl = VcsDataKeys.UPDATE_VIEW_SELECTED_PATH.getData(dc);

    ShowDiffAction.showDiffForChange(new MyIterableWrapper(iterable.iterator(), before, after), new MySelectionMarker(selectedUrl),
                                     project, new ShowDiffUIContext(true));
  }

  private static class MySelectionMarker implements Condition<Change> {
    private final String mySelectedPath;
    private boolean myFirstSelected;

    public MySelectionMarker(String selectedPath) {
      mySelectedPath = selectedPath;
    }

    public boolean value(Change change) {
      if (mySelectedPath == null) {
        if (myFirstSelected) {
          myFirstSelected = true;
          return true;
        }
        return false;
      }
      final MyCheckpointContentRevision revision = (MyCheckpointContentRevision)(change.getBeforeRevision() == null ? change.getAfterRevision() : change.getBeforeRevision());
      final String url = revision.getUrl();
      return mySelectedPath.equals(url);
    }
  }

  private static class MyIterableWrapper implements Iterable<Change> {
    private final Iterator<Pair<VirtualFilePointer, FileStatus>> myVfIterator;
    private final Label myBefore;
    private final Label myAfter;

    private MyIterableWrapper(Iterator<Pair<VirtualFilePointer, FileStatus>> vfIterator, final Label before, final Label after) {
      myVfIterator = vfIterator;
      myBefore = before;
      myAfter = after;
    }

    public Iterator<Change> iterator() {
      return new MyIteratorWrapper(myVfIterator, myBefore, myAfter);
    }
  }

  private static class MyLoader {
    private final Label myLabel;

    private MyLoader(Label label) {
      myLabel = label;
    }

    @Nullable
    public String convert(final VirtualFilePointer pointer) {
      if (pointer == null) return null;
      final String path = pointer.getPresentableUrl();
      final ByteContent byteContent = myLabel.getByteContent(FileUtil.toSystemIndependentName(path));
      if (byteContent == null || byteContent.isDirectory() || byteContent.getBytes() == null) {
        return null;
      }
      final VirtualFile vf = pointer.getFile();
      if (vf == null) {
        return LoadTextUtil.getTextByBinaryPresentation(byteContent.getBytes(), EncodingManager.getInstance().getDefaultCharset()).toString();
      } else {
        return LoadTextUtil.getTextByBinaryPresentation(byteContent.getBytes(), vf).toString();
      }
    }
  }

  private static class MyCheckpointContentRevision implements ContentRevision {
    private SoftReference<String> myContent;
    private final MyLoader myLoader;
    private final VirtualFilePointer myPointer;
    private final boolean myBefore;

    private MyCheckpointContentRevision(final VirtualFilePointer pointer, final MyLoader loader, final boolean before) {
      myLoader = loader;
      myPointer = pointer;
      myBefore = before;
    }

    public String getContent() throws VcsException {
      if (myContent != null) {
        final String s = myContent.get();
        if (s != null) {
          return s;
        }
      }

      final String loaded = myLoader.convert(myPointer);
      myContent = new SoftReference<String>(loaded);

      return loaded;
    }

    public String getUrl() {
      return myPointer.getUrl();
    }

    @NotNull
    public FilePath getFile() {
      final VirtualFile vf = myPointer.getFile();
      if (vf != null) {
        return new FilePathImpl(vf);
      }
      return new FilePathImpl(new File(myPointer.getPresentableUrl()), false);
    }

    @NotNull
    public VcsRevisionNumber getRevisionNumber() {
      return new VcsRevisionNumber() {
        public String asString() {
          return myBefore ? "Before update" : "After update";
        }

        public int compareTo(VcsRevisionNumber o) {
          return myBefore ? -1 : 1;
        }
      };
    }
  }

  private static class MyIteratorWrapper implements Iterator<Change> {
    private final MyLoader myBeforeLoader;
    private final MyLoader myAfterLoader;
    private final Iterator<Pair<VirtualFilePointer, FileStatus>> myVfIterator;

    public MyIteratorWrapper(final Iterator<Pair<VirtualFilePointer, FileStatus>> vfIterator, final Label before, final Label after) {
      myVfIterator = vfIterator;
      myBeforeLoader = new MyLoader(before);
      myAfterLoader = new MyLoader(after);
    }

    public boolean hasNext() {
      return myVfIterator.hasNext();
    }

    public Change next() {
      final Pair<VirtualFilePointer, FileStatus> pair = myVfIterator.next();
      final VirtualFilePointer pointer = pair.getFirst();

      MyCheckpointContentRevision before = new MyCheckpointContentRevision(pointer, myBeforeLoader, true);
      MyCheckpointContentRevision after = new MyCheckpointContentRevision(pointer, myAfterLoader, false);
      if (FileStatus.ADDED.equals(pair.getSecond())) {
        before = null;
      } else if (FileStatus.DELETED.equals(pair.getSecond())) {
        after = null;
      }
      return new Change(before, after, pair.getSecond());
    }

    public void remove() {
      throw new UnsupportedOperationException();
    }
  }
}
