// 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.Iterator;
import java.util.List;

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, final int contextLines,
      final int aSize, final 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 Iterable<Hunk>() {
      public Iterator<Hunk> iterator() {
        return new Iterator<Hunk>() {
          private int curIdx;

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

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

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

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

  private boolean combineA(final 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(final 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(final int ci, final 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(final Edit edit) {
      return aCur < edit.getEndA() || bCur < edit.getEndB();
    }
  }
}
