#ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
#define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_

#include "ArrayList.h"
#include "SinglyLinkedList.h"

template<typename T, typename count_t = uint8_t>
class HybridIterator: public LinkedElement<T>::Iterator,
		public ArrayList<T, count_t>::Iterator {
public:
	HybridIterator() {}

	HybridIterator(typename LinkedElement<T>::Iterator *iter) :
		LinkedElement<T>::Iterator(*iter), value(iter->value),
		linked(true) {

	}

	HybridIterator(LinkedElement<T> *start) :
		LinkedElement<T>::Iterator(start), value(start->value),
		linked(true) {

	}

	HybridIterator(typename ArrayList<T, count_t>::Iterator start,
			typename ArrayList<T, count_t>::Iterator end) :
			ArrayList<T, count_t>::Iterator(start), value(start.value),
			linked(false), end(end.value) {
		if (value == this->end) {
			value = NULL;
		}
	}

	HybridIterator(T *firstElement, T *lastElement) :
			ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
			linked(false), end(++lastElement) {
		if (value == end) {
			value = NULL;
		}
	}

	HybridIterator& operator++() {
		if (linked) {
			LinkedElement<T>::Iterator::operator++();
			if (LinkedElement<T>::Iterator::value != nullptr) {
				value = LinkedElement<T>::Iterator::value->value;
			} else {
				value = nullptr;
			}
		} else {
			ArrayList<T, count_t>::Iterator::operator++();
			value = ArrayList<T, count_t>::Iterator::value;

			if (value == end) {
				value = nullptr;
			}
		}
		return *this;
	}

	HybridIterator operator++(int) {
		HybridIterator tmp(*this);
		operator++();
		return tmp;
	}

	bool operator==(const HybridIterator& other) const {
		return value == other.value;
	}

	bool operator!=(const HybridIterator& other) const {
		return !(*this == other);
	}

	T operator*() {
		return *value;
	}

	T *operator->() {
		return value;
	}

	T* value = nullptr;

private:
	bool linked = false;
	T *end = nullptr;
};

#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */