/*
 * 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 git4idea.history.wholeTree;

import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.FilePathsHelper;
import com.intellij.openapi.vcs.diff.ItemLatestState;
import com.intellij.openapi.vcs.persistent.SmallMapSerializer;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.intellij.util.containers.SLRUMap;
import com.intellij.util.containers.ThrowableIterator;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.TaskDescriptor;
import com.intellij.util.continuation.Where;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import git4idea.GitRevisionNumber;
import git4idea.history.GitHistoryUtils;
import git4idea.history.browser.SHAHash;
import org.jetbrains.annotations.NotNull;

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

/**
 * !! application-level
 *
 * User: Irina.Chernushina
 * Date: 8/30/11
 * Time: 7:33 PM
 */
public class GitCommitsSequentialIndex implements GitCommitsSequentially {
  private final Object myLock;
  // to don't allow file reload while iterator is active
  private final File myListFile;

  // let it be simple
  private static final int ourInterval = 1000;
  private static final int ourRecordSize = 40 + 1 + 10 + 1;
  
  // start-to-now, time -> ascending. times at points each ourInterval commits written in file
  private final SLRUMap<VirtualFile, List<Long>> myPacks;
  // offset in file, root file
  private final SLRUMap<Pair<Long, VirtualFile>, List<Pair<AbstractHash, Long>>> myCache;
  private final File myDir;
  // loaded roots to files mapping
  private SmallMapSerializer<String, String> myState;
  private static final Logger LOG = Logger.getInstance("#git4idea.history.wholeTree.GitCommitsSequentialIndex");

  public GitCommitsSequentialIndex() {
    myLock = new Object();
    final File vcsFile = new File(PathManager.getSystemPath(), "vcs");
    myDir = new File(vcsFile, "git_line");
    myDir.mkdirs();
    // will contain list of roots mapped to
    myListFile = new File(myDir, "repository_index");
    myCache = new SLRUMap<Pair<Long, VirtualFile>, List<Pair<AbstractHash, Long>>>(10,10);
    myPacks = new SLRUMap<VirtualFile, List<Long>>(10,10);
  }

  public void activate() {
    synchronized (myLock) {
      if (myState == null) {
        myState = new SmallMapSerializer<String, String>(myListFile, new EnumeratorStringDescriptor(), createExternalizer());
      }
    }
  }

  public void deactivate() {
    synchronized (myLock) {
      if (myState == null) {
        LOG.info("Deactivate without activate");
        return;
      }
      myState.force();
      myState = null;
    }
  }
  
  private String getPutRootPath(final VirtualFile root) throws VcsException {
    synchronized (myLock) {
      String key = FilePathsHelper.convertPath(root);
      final String storedName = myState.get(key);
      if (storedName != null) return storedName;
      File tempFile = null;
      try {
        tempFile = File.createTempFile(root.getNameWithoutExtension(), ".dat", myDir);
      }
      catch (IOException e) {
        throw new VcsException(e);
      }
      String path = tempFile.getPath();
      myState.put(key, path);
      myState.force();
      return path;
    }
  }

  private DataExternalizer<String> createExternalizer() {
    return new DataExternalizer<String>() {
      @Override
      public void save(@NotNull DataOutput out, String value) throws IOException {
        out.writeUTF(value);
      }

      @Override
      public String read(@NotNull DataInput in) throws IOException {
        return in.readUTF();
      }
    };
  }

  // go back!!
  private class MyIterator implements ThrowableIterator<Pair<AbstractHash, Long>, VcsException> {
    private final VirtualFile myFile;
    private int myIdx;
    private final int myPacksSize;
    private Iterator<Pair<AbstractHash, Long>> myCurrent;

    private MyIterator(final VirtualFile file, final int idx, final int packsSize) throws VcsException {
      myFile = file;
      myIdx = idx;
      myPacksSize = packsSize;
      initIterator();
    }

    void initIterator() throws VcsException {
      final Pair<Long, VirtualFile> key = new Pair<Long, VirtualFile>((long) myIdx, myFile);
      List<Pair<AbstractHash, Long>> cached = myCache.get(key);
      if (cached == null) {
        cached = loadPack(myFile, myIdx);
        myCache.put(key, cached);
      }
      myCurrent = cached.iterator();
    }

    @Override
    public boolean hasNext() {
      return myCurrent.hasNext() || myIdx < myPacksSize;
    }

    @Override
    public Pair<AbstractHash, Long> next() throws VcsException {
      if (myCurrent.hasNext()) {
        return myCurrent.next();
      }
      ++ myIdx;
      initIterator();
      return myCurrent.next();
    }

    @Override
    public void remove() throws VcsException {
      throw new UnsupportedOperationException();
    }
  }

  private List<Long> getPacksWithLoad(VirtualFile file, String pathToFile) throws VcsException {
    List<Long> packs = myPacks.get(file);
    if (packs == null) {
      // reload
      packs = loadPacks(file, pathToFile);
    }
    return packs;
  }

  private int findLineTroughPacks(VirtualFile file, String pathToFile, final long ts) throws VcsException {
    synchronized (myLock) {
      List<Long> packs = getPacksWithLoad(file, pathToFile);
      if (packs == null) {
        return -1;
      }
      int found = Collections.binarySearch(packs, ts, Collections.<Long>reverseOrder());
      if (found >= 0) {
        // can find one of equal
        while (found > 0 && packs.get(found - 1) == ts) {
          -- found;
        }
        return found == 0 ? 0 : (found - 1);
      } else {
        int insertPlace = - found - 1;
        // todo possibly, if here we see that ts asked for is greater than what we cached, we can raise exception or reload some stuff
        return insertPlace == 0 ? 0 : (insertPlace - 1);
      }
    }
  }

  public static Pair<AbstractHash, Long> parseRecord(final String line) throws VcsException {
    int spaceIdx = line.indexOf(' ');
    // todo concern index file deletion and re-ask
    if (spaceIdx == -1) throw new VcsException("Can not parse written index file");
    try {
      long next = Long.parseLong(line.substring(spaceIdx + 1));
      return new Pair<AbstractHash, Long>(AbstractHash.create(line.substring(0, spaceIdx)), next * 1000);
      // todo concern index file deletion and re-ask
    } catch (NumberFormatException e) {
      throw new VcsException(e);
    }
  }
  
  private List<Pair<AbstractHash, Long>> loadPack(final VirtualFile file, final long packNumber) throws VcsException {
    final ArrayList<Pair<AbstractHash, Long>> data = new ArrayList<Pair<AbstractHash, Long>>();
    synchronized (myLock) {
      String key = FilePathsHelper.convertPath(file);
      String outFileName = myState.get(key);
      RandomAccessFile raf = null;
      try {
        raf = new RandomAccessFile(outFileName, "r");
        long len = raf.length();
        long offset = len - packNumber * ourInterval * ourRecordSize;

        long recordsInPiece = offset / ourRecordSize;
        long size = recordsInPiece >= ourInterval ? ourInterval : recordsInPiece;
        ((ArrayList) data).ensureCapacity((int) size);

        raf.seek(offset - size * ourRecordSize);
        for (int i = 0; i < size && i < len/ourRecordSize; i++) {
          String line = raf.readLine();
          data.add(parseRecord(line));
        }
      }
      catch (FileNotFoundException e) {
        throw new VcsException(e);
      }
      catch (IOException e) {
        throw new VcsException(e);
      }
      finally {
        try {
          if (raf != null) {
            raf.close();
          }
        }
        catch (IOException e) {
          throw new VcsException(e);
        }
      }
      Collections.reverse(data);
      myCache.put(new Pair<Long, VirtualFile>(packNumber, file), data);
    }
    return data;
  }

  private ArrayList<Long> loadPacks(VirtualFile file, String pathToFile) throws VcsException {
    synchronized (myLock) {
      final ArrayList<Long> packs = new ArrayList<Long>();
      RandomAccessFile raf = null;
      try {
        raf = new RandomAccessFile(pathToFile, "r");
        long len = raf.length();
        ((ArrayList) packs).ensureCapacity((int)(len/(ourRecordSize * ourInterval)) + 1);

        for (long i = (len - ourRecordSize); i >= 0; i-= (ourRecordSize * ourInterval)) {
          raf.seek(i);
          final String line = raf.readLine();
          packs.add(parseRecord(line).getSecond());
        }
      }
      catch (FileNotFoundException e) {
        throw new VcsException(e);
      }
      catch (IOException e) {
        throw new VcsException(e);
      }
      finally {
        try {
          if (raf != null) {
            raf.close();
          }
        }
        catch (IOException e) {
          throw new VcsException(e);
        }
      }

      myPacks.put(file, packs);
      return packs;
    }
  }

  @Override
  public void iterateDescending(VirtualFile file,
                                long commitTime,
                                Processor<Pair<AbstractHash, Long>> consumer) throws VcsException {
    final String key = FilePathsHelper.convertPath(file);
    synchronized (myLock) {
      String pathToFile = myState.get(key);
      if (pathToFile == null || ! new File(pathToFile).exists()) return;
      int idx;
      if (commitTime == -1) {
        idx = 0;
      } else {
        idx = findLineTroughPacks(file, pathToFile, commitTime);
        if (idx == -1) return;
      }

      List<Long> packs = getPacksWithLoad(file, pathToFile);
      final MyIterator iterator = new MyIterator(file, idx, packs.size());
      if (commitTime != -1) {
        while (iterator.hasNext()) {
          final Pair<AbstractHash, Long> next = iterator.next();
          if (next.getSecond() <= commitTime) {
            if (! consumer.process(next)) {
              return;
            }
            break;
          }
        }
      }
      while (iterator.hasNext()) {
        final Pair<AbstractHash, Long> next = iterator.next();
        if (! consumer.process(next)) break;
      }
    }
  }

  @Override
  public void pushUpdate(final Project project, final VirtualFile file, final ContinuationContext context) {
    context.next(new LoadTask(file, project));
  }

  private class LoadTask extends TaskDescriptor {
    private final Project myProject;
    private final VirtualFile myFile;

    private LoadTask(VirtualFile file, Project project) {
      super("Refresh repository " + file.getPath() + " cache", Where.POOLED);
      myFile = file;
      myProject = project;
    }

    @Override
    public void run(ContinuationContext context) {
      // we need a lock here to prevent parallel access to file from our application
      // (generally possible)
      // todo consider lock on file name
      synchronized (myLock) {
        try {
          loadImpl();
        }
        catch (VcsException e) {
          context.cancelEverything();
          if (! context.handleException(e, false)) {
            VcsBalloonProblemNotifier.showOverChangesView(myProject, e.getMessage(), MessageType.ERROR);
            // and exit, do not ping
          }
        }
      }
    }

    private void loadImpl() throws VcsException {
      final AbstractHash[] latestWrittenHash = new AbstractHash[1];
      final Long[] latestWrittenTime = new Long[1];
      iterateDescending(myFile, -1, new Processor<Pair<AbstractHash, Long>>() {
        @Override
        public boolean process(Pair<AbstractHash, Long> abstractHashLongPair) {
          latestWrittenHash[0] = abstractHashLongPair.getFirst();
          latestWrittenTime[0] = abstractHashLongPair.getSecond();
          return false;
        }
      });
      if (latestWrittenHash[0] != null) {
        ItemLatestState lastRevision = GitHistoryUtils.getLastRevision(myProject, new FilePathImpl(myFile));
        if (lastRevision == null) {
          // no history at the moment
          return;
        }
        if (lastRevision.isItemExists() && ((GitRevisionNumber) lastRevision.getNumber()).getRev().equals(latestWrittenHash[0].getString())) {
          // no refresh needed
          return;
        }
        appendHistory(latestWrittenTime[0], latestWrittenHash[0]);
      } else {
        initHistory();
      }
    }

    private void initHistory() throws VcsException {
      final String outFilePath = getPutRootPath(myFile);
      GitHistoryUtils.dumpFullHistory(myProject, myFile, outFilePath);
    }

    private void appendHistory(final long since, final AbstractHash hash) throws VcsException {
      final String outFilePath = getPutRootPath(myFile);

      final List<Pair<SHAHash,Date>> pairs =
              GitHistoryUtils.onlyHashesHistory(myProject, new FilePathImpl(myFile), "--all", "--date-order", "--full-history", "--sparse",
                                                "--after=" + (since/1000));
      if (pairs.isEmpty()) return;
      final String startAsString = hash.getString();

      Iterator<Pair<SHAHash, Date>> iterator = pairs.iterator();
      while (iterator.hasNext()) {
        Pair<SHAHash, Date> next = iterator.next();
        if (next.getFirst().getValue().equals(startAsString)) {
          break;
        }
      }

      OutputStream stream = null;
      try {
        stream = new BufferedOutputStream(new FileOutputStream(new File(outFilePath), true));
        while (iterator.hasNext()) {
          Pair<SHAHash, Date> next = iterator.next();
          stream.write(new StringBuilder().append(next.getFirst().getValue()).append(" ").
                  append(next.getSecond().getTime()).append('\n').toString().getBytes(CharsetToolkit.UTF8_CHARSET));
        }
      }
      catch (FileNotFoundException e) {
        throw new VcsException(e);
      }
      catch (IOException e) {
        throw new VcsException(e);
      }
      finally {
        try {
          if (stream != null) {
            stream.close();
          }
        }
        catch (IOException e) {
          throw new VcsException(e);
        }
      }
    }
  }
}
