// 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 java.util.Iterator;
import java.util.List;
import org.eclipse.jgit.diff.Edit;

public class EditList {
  private final List<Edit> edits;
  private final int context;
  private final int aSize;
  private final int bSize;

  public EditList(final List<Edit> edits, int contextLines, int aSize, int bSize) {
    this.edits = edits;
    this.context = contextLines;
    this.aSize = aSize;
    this.bSize = bSize;
  }

  public List<Edit> getEdits() {
    return edits;
  }

  public Iterable<Hunk> getHunks() {
    return () ->
        new Iterator<Hunk>() {
          private int curIdx;

          @Override
          public boolean hasNext() {
            return curIdx < edits.size();
          }

          @Override
          public Hunk next() {
            final int c = curIdx;
            final int e = findCombinedEnd(c);
            curIdx = e + 1;
            return new Hunk(c, e);
          }

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

  private int findCombinedEnd(int i) {
    int end = i + 1;
    while (end < edits.size() && (combineA(end) || combineB(end))) {
      end++;
    }
    return end - 1;
  }

  private boolean combineA(int i) {
    final Edit s = edits.get(i);
    final Edit e = edits.get(i - 1);
    // + 1 to prevent '... skipping 1 common line ...' messages.
    return s.getBeginA() - e.getEndA() <= 2 * context + 1;
  }

  private boolean combineB(int i) {
    final int s = edits.get(i).getBeginB();
    final int e = edits.get(i - 1).getEndB();
    // + 1 to prevent '... skipping 1 common line ...' messages.
    return s - e <= 2 * context + 1;
  }

  public class Hunk {
    private int curIdx;
    private Edit curEdit;
    private final int endIdx;
    private final Edit endEdit;

    private int aCur;
    private int bCur;
    private final int aEnd;
    private final int bEnd;

    private Hunk(int ci, int ei) {
      curIdx = ci;
      endIdx = ei;
      curEdit = edits.get(curIdx);
      endEdit = edits.get(endIdx);

      aCur = Math.max(0, curEdit.getBeginA() - context);
      bCur = Math.max(0, curEdit.getBeginB() - context);
      aEnd = Math.min(aSize, endEdit.getEndA() + context);
      bEnd = Math.min(bSize, endEdit.getEndB() + context);
    }

    public int getCurA() {
      return aCur;
    }

    public int getCurB() {
      return bCur;
    }

    public Edit getCurEdit() {
      return curEdit;
    }

    public int getEndA() {
      return aEnd;
    }

    public int getEndB() {
      return bEnd;
    }

    public void incA() {
      aCur++;
    }

    public void incB() {
      bCur++;
    }

    public void incBoth() {
      incA();
      incB();
    }

    public boolean isStartOfFile() {
      return aCur == 0 && bCur == 0;
    }

    public boolean isContextLine() {
      return !isModifiedLine();
    }

    public boolean isDeletedA() {
      return curEdit.getBeginA() <= aCur && aCur < curEdit.getEndA();
    }

    public boolean isInsertedB() {
      return curEdit.getBeginB() <= bCur && bCur < curEdit.getEndB();
    }

    public boolean isModifiedLine() {
      return isDeletedA() || isInsertedB();
    }

    public boolean next() {
      if (!in(curEdit)) {
        if (curIdx < endIdx) {
          curEdit = edits.get(++curIdx);
        }
      }
      return aCur < aEnd || bCur < bEnd;
    }

    private boolean in(Edit edit) {
      return aCur < edit.getEndA() || bCur < edit.getEndB();
    }
  }
}
