/*
 * Copyright 2000-2006 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.
 */

/*
 * Created by IntelliJ IDEA.
 * User: yole
 * Date: 28.11.2006
 * Time: 17:48:18
 */
package org.jetbrains.idea.svn.history;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.peer.PeerFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNRevision;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

public class SvnRepositoryContentRevision implements ContentRevision {
  private final String myRepositoryRoot;
  private final SvnVcs myVcs;
  private final String myPath;
  @Nullable private final FilePath myLocalPath;
  private final long myRevision;
  private String myContent;

  SvnRepositoryContentRevision(final SvnVcs vcs, final String repositoryRoot, final String path, @Nullable final FilePath localPath,
                                      final long revision) {
    myVcs = vcs;
    myPath = path;
    myRepositoryRoot = repositoryRoot;
    myLocalPath = localPath;
    myRevision = revision;
  }

  @Nullable
  public String getContent() throws VcsException {
    if (myContent == null) {
      final OutputStream buffer = loadContent();
      myContent = buffer.toString();
    }
    return myContent;
  }

  protected ByteArrayOutputStream loadContent() throws VcsException {
    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    ContentLoader loader = new ContentLoader(myPath, buffer, myRevision);
    if (ApplicationManager.getApplication().isDispatchThread()) {
      ProgressManager.getInstance()
        .runProcessWithProgressSynchronously(loader, SvnBundle.message("progress.title.loading.file.content"), false, null);
    }
    else {
      loader.run();
    }
    final SVNException exception = loader.getException();
    if (exception != null) {
      throw new VcsException(exception);
    }
    return buffer;
  }

  @NotNull
  public FilePath getFile() {
    if (myLocalPath != null) {
      return myLocalPath;
    }
    return PeerFactory.getInstance().getVcsContextFactory().createFilePathOnNonLocal(myPath, false);
  }

  @NotNull
  public VcsRevisionNumber getRevisionNumber() {
    return new SvnRevisionNumber(SVNRevision.create(myRevision));
  }

  public static SvnRepositoryContentRevision create(final SvnVcs vcs, final String repositoryRoot, final String path, 
                                                    @Nullable final FilePath localPath, final long revision) {
    int fileNamePos = path.lastIndexOf('/');
    if (fileNamePos >= 0) {
      String fileName = path.substring(fileNamePos);
      final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName);
      if (fileType.isBinary()) {
        return new SvnRepositoryBinaryContentRevision(vcs, repositoryRoot, path, localPath, revision);
      }
    }
    return new SvnRepositoryContentRevision(vcs, repositoryRoot, path, localPath, revision);
  }

  private class ContentLoader implements Runnable {
    private final String myPath;
    private final long myRevision;
    private final OutputStream myDst;
    private SVNException myException;

    public ContentLoader(String path, OutputStream dst, long revision) {
      myPath = path;
      myDst = dst;
      myRevision = revision;
    }

    public SVNException getException() {
      return myException;
    }

    public void run() {
      ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
      if (progress != null) {
        progress.setText(SvnBundle.message("progress.text.loading.contents", myPath));
        progress.setText2(SvnBundle.message("progress.text2.revision.information", myRevision));
      }
      try {
        String fullPath = myRepositoryRoot;
        if (!fullPath.endsWith("/") && !myPath.startsWith("/")) {
          fullPath += "/";
        }
        fullPath += myPath;
        SVNRepository repository = myVcs.createRepository(fullPath);
        try {
          repository.getFile("", myRevision, null, myDst);
        }
        finally {
          repository.closeSession();
        }
      }
      catch (SVNException e) {
        myException = e;
      }
    }
  }
}
@@ -1193,32 +1193,80 @@
 ileTypeManager;%0A
+import com.intellij.openapi.vfs.CharsetToolkit;%0A
 import com.intel
@@ -2420,24 +2420,33 @@
       final 
+ByteArray
 OutputStream
@@ -2492,24 +2492,57 @@
 t = 
-buffer.toString(
+CharsetToolkit.bytesToString(buffer.toByteArray()
 );%0A 

correct encoding for loading SVN repository content revisions (IDEADEV-23631)