package me.eater.threedom.utils import java.util.* class OrderedSet() : MutableSet, MutableList { override val size get() = items.size private val set: MutableSet = mutableSetOf() private val items: MutableList = mutableListOf() constructor(elements: Collection) : this() { addAll(elements) } override fun contains(element: T) = set.contains(element) override fun containsAll(elements: Collection) = set.containsAll(elements) override fun isEmpty() = items.isEmpty() override fun iterator() = items.iterator() override operator fun get(index: Int) = items[index] override fun spliterator(): Spliterator = set.spliterator() override fun indexOf(element: T): Int = items.indexOf(element) override fun lastIndexOf(element: T): Int = indexOf(element) override fun listIterator(): MutableOrderedSetListIterator = MutableOrderedSetListIterator(this) override fun listIterator(index: Int): MutableOrderedSetListIterator = MutableOrderedSetListIterator(this, index) override fun subList(fromIndex: Int, toIndex: Int): OrderedSet = OrderedSet(items.subList(fromIndex, toIndex)) override fun add(element: T): Boolean { if (set.add(element)) { items.add(element) return true } return false } override fun addAll(elements: Collection): Boolean { return elements.map(::add).any() } override fun clear() { set.clear() items.clear() } override fun remove(element: T): Boolean { if (set.remove(element)) { items.remove(element) return true } return false } override fun removeAll(elements: Collection): Boolean { return elements.map(::remove).any() } override fun retainAll(elements: Collection): Boolean { return set.toSet().map { if (elements.contains(it)) { false } else { remove(it) } }.any() } override fun add(index: Int, element: T) { if (set.add(element)) { items.add(index, element) } } override fun addAll(index: Int, elements: Collection): Boolean { return items.addAll(index, elements.filter(set::add)) } override fun removeAt(index: Int): T { set.remove(items[index]) return items.removeAt(index) } override fun set(index: Int, element: T): T { if (!set.add(element)) { return element } val old = items[index] items[index] = element remove(old) set.add(element) return old } }