package jdk.internal.jline.console.history;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import static jdk.internal.jline.internal.Preconditions.checkNotNull;
public class MemoryHistory
implements History
{
public static final int DEFAULT_MAX_SIZE = 500;
private final LinkedList<CharSequence> items = new LinkedList<CharSequence>();
private int maxSize = DEFAULT_MAX_SIZE;
private boolean ignoreDuplicates = true;
private boolean autoTrim = false;
private int offset = 0;
private int index = 0;
public void setMaxSize(final int maxSize) {
this.maxSize = maxSize;
maybeResize();
}
public int getMaxSize() {
return maxSize;
}
public boolean isIgnoreDuplicates() {
return ignoreDuplicates;
}
public void setIgnoreDuplicates(final boolean flag) {
this.ignoreDuplicates = flag;
}
public boolean isAutoTrim() {
return autoTrim;
}
public void setAutoTrim(final boolean flag) {
this.autoTrim = flag;
}
public int size() {
return items.size();
}
public boolean isEmpty() {
return items.isEmpty();
}
public int index() {
return offset + index;
}
public void clear() {
items.clear();
offset = 0;
index = 0;
}
public CharSequence get(final int index) {
return items.get(index - offset);
}
public void set(int index, CharSequence item) {
items.set(index - offset, item);
}
public void add(CharSequence item) {
checkNotNull(item);
if (isAutoTrim()) {
item = String.valueOf(item).trim();
}
if (isIgnoreDuplicates()) {
if (!items.isEmpty() && item.equals(items.getLast())) {
return;
}
}
internalAdd(item);
}
public CharSequence remove(int i) {
return items.remove(i);
}
public CharSequence removeFirst() {
return items.removeFirst();
}
public CharSequence removeLast() {
return items.removeLast();
}
protected void internalAdd(CharSequence item) {
items.add(item);
maybeResize();
}
public void replace(final CharSequence item) {
items.removeLast();
add(item);
}
private void maybeResize() {
while (size() > getMaxSize()) {
items.removeFirst();
offset++;
}
index = size();
}
public ListIterator<Entry> entries(final int index) {
return new EntriesIterator(index - offset);
}
public ListIterator<Entry> entries() {
return entries(offset);
}
public Iterator<Entry> iterator() {
return entries();
}
private static class EntryImpl
implements Entry
{
private final int index;
private final CharSequence value;
public EntryImpl(int index, CharSequence value) {
this.index = index;
this.value = value;
}
public int index() {
return index;
}
public CharSequence value() {
return value;
}
@Override
public String toString() {
return String.format("%d: %s", index, value);
}
}
private class EntriesIterator
implements ListIterator<Entry>
{
private final ListIterator<CharSequence> source;
private EntriesIterator(final int index) {
source = items.listIterator(index);
}
public Entry next() {
if (!source.hasNext()) {
throw new NoSuchElementException();
}
return new EntryImpl(offset + source.nextIndex(), source.next());
}
public Entry previous() {
if (!source.hasPrevious()) {
throw new NoSuchElementException();
}
return new EntryImpl(offset + source.previousIndex(), source.previous());
}
public int nextIndex() {
return offset + source.nextIndex();
}
public int previousIndex() {
return offset + source.previousIndex();
}
public boolean hasNext() {
return source.hasNext();
}
public boolean hasPrevious() {
return source.hasPrevious();
}
public void remove() {
throw new UnsupportedOperationException();
}
public void set(final Entry entry) {
throw new UnsupportedOperationException();
}
public void add(final Entry entry) {
throw new UnsupportedOperationException();
}
}
public boolean moveToLast() {
int lastEntry = size() - 1;
if (lastEntry >= 0 && lastEntry != index) {
index = size() - 1;
return true;
}
return false;
}
public boolean moveTo(int index) {
index -= offset;
if (index >= 0 && index < size() ) {
this.index = index;
return true;
}
return false;
}
public boolean moveToFirst() {
if (size() > 0 && index != 0) {
index = 0;
return true;
}
return false;
}
public void moveToEnd() {
index = size();
}
public CharSequence current() {
if (index >= size()) {
return "";
}
return items.get(index);
}
public boolean previous() {
if (index <= 0) {
return false;
}
index--;
return true;
}
public boolean next() {
if (index >= size()) {
return false;
}
index++;
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Entry e : this) {
sb.append(e.toString() + "\n");
}
return sb.toString();
}
}