package com.hiwhitley.datastructure;

import java.util.Arrays;

/**
 * Created by hiwhitley on 17-3-16.
 */
public class ResizableArrayBag<T> implements BagInterface<T> {

    private T[] bag;
    private static final int DEFAULT_INITIAL_CAPACITY = 25;
    private int numberOfEntries;

    public ResizableArrayBag() {
        this(DEFAULT_INITIAL_CAPACITY);
    }

    public ResizableArrayBag(int capacity) {
        numberOfEntries = 0;
        T[] tmpBag = (T[]) new Object[capacity];
        bag = tmpBag;
    }

    @Override
    public int getCurrentSize() {
        return numberOfEntries;
    }

    @Override
    public boolean isFull() {
        return false;
    }// end isFull

    @Override
    public boolean isEmpty() {
        return numberOfEntries == 0;
    }

    @Override
    public boolean add(T newEntry) {
        ensureCapacity();
        bag[numberOfEntries] = newEntry;
        numberOfEntries++;
        return true;
    }

    @Override
    public T remove() {
        T result = removeEntry(numberOfEntries - 1);
        return result;
    }

    @Override
    public boolean remove(T anEntry) {
        int index = getIndexOf(anEntry);
        T result = removeEntry(index);
        return anEntry.equals(result);
    }

    @Override
    public void clear() {
        while (!isEmpty()) {
            remove();
        }
    }

    @Override
    public int getFrequencyOf(T anEntry) {
        int counter = 0;
        for (int i = 0; i < numberOfEntries; i++) {
            if (anEntry.equals(bag[i])) {
                counter++;
            }
        }
        return counter;
    }

    @Override
    public boolean contains(T anEntry) {
        return getIndexOf(anEntry) > -1;
    }

    @Override
    public T[] toArray() {
        return Arrays.copyOf(bag, bag.length);
    }

    private T removeEntry(int givenIndex) {
        T result = null;
        if (!isEmpty() && (givenIndex >= 0)) {
            result = bag[givenIndex];
            numberOfEntries--;
            bag[givenIndex] = bag[numberOfEntries];
            bag[numberOfEntries] = null;
        }
        return result;
    }

    private int getIndexOf(T anEntry) {
        int where = -1;
        for (int i = 0; (where == -1) && (i < numberOfEntries); i++) {
            if (anEntry.equals(bag[i])) {
                where = i;
            }
        }
        return where;
    }

    private void ensureCapacity() {
        if (numberOfEntries == bag.length) {
            bag = Arrays.copyOf(bag, bag.length * 2);
        }
    }
}
