// Copyright (C) 2009 The Android Open Source Project
//
// 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.google.gerrit.prettify.common;


import org.eclipse.jgit.diff.Edit;

import java.util.ArrayList;
import java.util.List;

public class SparseFileContent {
  protected String path;
  protected List<Range> ranges;
  protected int size;
  protected boolean missingNewlineAtEnd;

  private transient int currentRangeIdx;

  public SparseFileContent() {
    ranges = new ArrayList<>();
  }

  public int size() {
    return size;
  }

  public void setSize(final int s) {
    size = s;
  }

  public boolean isMissingNewlineAtEnd() {
    return missingNewlineAtEnd;
  }

  public void setMissingNewlineAtEnd(final boolean missing) {
    missingNewlineAtEnd = missing;
  }

  public String getPath() {
    return path;
  }

  public void setPath(String filePath) {
    path = filePath;
  }

  public boolean isWholeFile() {
    if (size == 0) {
      return true;

    } else if (1 == ranges.size()) {
      Range r = ranges.get(0);
      return r.base == 0 && r.end() == size;

    } else {
      return false;
    }
  }

  public String get(final int idx) {
    final String line = getLine(idx);
    if (line == null) {
      throw new ArrayIndexOutOfBoundsException(idx);
    }
    return line;
  }

  public boolean contains(final int idx) {
    return getLine(idx) != null;
  }

  public int first() {
    return ranges.isEmpty() ? size() : ranges.get(0).base;
  }

  public int next(final int idx) {
    // Most requests are sequential in nature, fetching the next
    // line from the current range, or the immediate next range.
    //
    int high = ranges.size();
    if (currentRangeIdx < high) {
      Range cur = ranges.get(currentRangeIdx);
      if (cur.contains(idx + 1)) {
        return idx + 1;
      }

      if (++currentRangeIdx < high) {
        // Its not plus one, its the base of the next range.
        //
        return ranges.get(currentRangeIdx).base;
      }
    }

    // Binary search for the current value, since we know its a sorted list.
    //
    int low = 0;
    do {
      final int mid = (low + high) / 2;
      final Range cur = ranges.get(mid);

      if (cur.contains(idx)) {
        if (cur.contains(idx + 1)) {
          // Trivial plus one case above failed due to wrong currentRangeIdx.
          // Reset the cache so we don't miss in the future.
          //
          currentRangeIdx = mid;
          return idx + 1;
        }

        if (mid + 1 < ranges.size()) {
          // Its the base of the next range.
          currentRangeIdx = mid + 1;
          return ranges.get(currentRangeIdx).base;
        }

        // No more lines in the file.
        //
        return size();
      }

      if (idx < cur.base)
        high = mid;
      else
        low = mid + 1;
    } while (low < high);

    return size();
  }

  public int mapIndexToLine(int arrayIndex) {
    final int origIndex = arrayIndex;
    for (Range r : ranges) {
      if (arrayIndex < r.lines.size()) {
        return r.base + arrayIndex;
      }
      arrayIndex -= r.lines.size();
    }
    throw new ArrayIndexOutOfBoundsException(origIndex);
  }

  private String getLine(final int idx) {
    // Most requests are sequential in nature, fetching the next
    // line from the current range, or the next range.
    //
    int high = ranges.size();
    if (currentRangeIdx < high) {
      Range cur = ranges.get(currentRangeIdx);
      if (cur.contains(idx)) {
        return cur.get(idx);
      }

      if (++currentRangeIdx < high) {
        final Range next = ranges.get(currentRangeIdx);
        if (next.contains(idx)) {
          return next.get(idx);
        }
      }
    }

    // Binary search for the range, since we know its a sorted list.
    //
    if (ranges.isEmpty()) {
      return null;
    }

    int low = 0;
    do {
      final int mid = (low + high) / 2;
      final Range cur = ranges.get(mid);
      if (cur.contains(idx)) {
        currentRangeIdx = mid;
        return cur.get(idx);
      }
      if (idx < cur.base)
        high = mid;
      else
        low = mid + 1;
    } while (low < high);
    return null;
  }

  public void addLine(final int i, final String content) {
    final Range r;
    if (!ranges.isEmpty() && i == last().end()) {
      r = last();
    } else {
      r = new Range(i);
      ranges.add(r);
    }
    r.lines.add(content);
  }

  private Range last() {
    return ranges.get(ranges.size() - 1);
  }

  public String asString() {
    final StringBuilder b = new StringBuilder();
    for (Range r : ranges) {
      for (String l : r.lines) {
        b.append(l);
        b.append('\n');
      }
    }
    if (0 < b.length() && isMissingNewlineAtEnd()) {
      b.setLength(b.length() - 1);
    }
    return b.toString();
  }

  public SparseFileContent apply(SparseFileContent a, List<Edit> edits) {
    EditList list = new EditList(edits, size, a.size(), size);
    ArrayList<String> lines = new ArrayList<>(size);
    for (final EditList.Hunk hunk : list.getHunks()) {
      while (hunk.next()) {
        if (hunk.isContextLine()) {
          if (contains(hunk.getCurB())) {
            lines.add(get(hunk.getCurB()));
          } else {
            lines.add(a.get(hunk.getCurA()));
          }
          hunk.incBoth();
          continue;
        }

        if (hunk.isDeletedA()) {
          hunk.incA();
        }

        if (hunk.isInsertedB()) {
          lines.add(get(hunk.getCurB()));
          hunk.incB();
        }
      }
    }

    Range range = new Range();
    range.lines = lines;

    SparseFileContent r = new SparseFileContent();
    r.setSize(lines.size());
    r.setMissingNewlineAtEnd(isMissingNewlineAtEnd());
    r.setPath(getPath());
    r.ranges.add(range);

    return r;
  }

  @Override
  public String toString() {
    final StringBuilder b = new StringBuilder();
    b.append("SparseFileContent[\n");
    for (Range r : ranges) {
      b.append("  ");
      b.append(r.toString());
      b.append('\n');
    }
    b.append("]");
    return b.toString();
  }

  static class Range {
    protected int base;
    protected List<String> lines;

    private Range(final int b) {
      base = b;
      lines = new ArrayList<>();
    }

    protected Range() {
    }

    private String get(final int i) {
      return lines.get(i - base);
    }

    private int end() {
      return base + lines.size();
    }

    private boolean contains(final int i) {
      return base <= i && i < end();
    }

    @Override
    public String toString() {
      // Usage of [ and ) is intentional to denote inclusive/exclusive range
      return "Range[" + base + "," + end() + ")";
    }
  }
}
