package ru.dbotthepony.mc.otm.storage.optics

import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.storage.IStorageAcceptor
import ru.dbotthepony.mc.otm.storage.IStorageComponent
import ru.dbotthepony.mc.otm.storage.IStorageProvider
import ru.dbotthepony.mc.otm.storage.IVirtualStorageComponent
import ru.dbotthepony.mc.otm.storage.StorageStack
import ru.dbotthepony.mc.otm.storage.powered.PoweredComponent
import ru.dbotthepony.mc.otm.storage.powered.PoweredStorageAcceptor
import ru.dbotthepony.mc.otm.storage.powered.PoweredStorageProvider
import ru.dbotthepony.mc.otm.storage.powered.PoweredVirtualComponent
import java.util.function.IntSupplier
import java.util.function.Supplier

fun <S : StorageStack<S>> IStorageAcceptor<S>.insertPriority(priority: IntSupplier): IStorageAcceptor<S> {
	return InsertPriority(this, priority)
}

fun <S : StorageStack<S>> IStorageAcceptor<S>.insertPriority(priority: Int): IStorageAcceptor<S> {
	return InsertPriority(this) { priority }
}

fun <S : StorageStack<S>> IStorageProvider<S>.extractPriority(priority: IntSupplier): IStorageProvider<S> {
	return ExtractPriority(this, priority)
}

fun <S : StorageStack<S>> IStorageProvider<S>.extractPriority(priority: Int): IStorageProvider<S> {
	return ExtractPriority(this) { priority }
}

fun <S : StorageStack<S>> IStorageComponent<S>.priority(priority: IntSupplier): IStorageComponent<S> {
	return ModifyPriority(this, priority, priority)
}

fun <S : StorageStack<S>> IStorageComponent<S>.priority(priority: Int): IStorageComponent<S> {
	return ModifyPriority(this, { priority }, { priority })
}

fun <S : StorageStack<S>> IStorageComponent<S>.priority(insertPriority: IntSupplier, extractPriority: IntSupplier): IStorageComponent<S> {
	return ModifyPriority(this, insertPriority, extractPriority)
}

fun <S : StorageStack<S>> IStorageComponent<S>.priority(insertPriority: Int, extractPriority: Int): IStorageComponent<S> {
	return ModifyPriority(this, { insertPriority }, { extractPriority })
}

fun <S : StorageStack<S>> IStorageAcceptor<S>.powered(energy: Supplier<IMatteryEnergyStorage>): IStorageAcceptor<S> {
	return PoweredStorageAcceptor(this, energy)
}

fun <S : StorageStack<S>> IStorageAcceptor<S>.powered(energy: IMatteryEnergyStorage): IStorageAcceptor<S> {
	return PoweredStorageAcceptor(this) { energy }
}

fun <S : StorageStack<S>> IStorageProvider<S>.powered(energy: Supplier<IMatteryEnergyStorage>): IStorageProvider<S> {
	return PoweredStorageProvider(this, energy)
}

fun <S : StorageStack<S>> IStorageProvider<S>.powered(energy: IMatteryEnergyStorage): IStorageProvider<S> {
	return PoweredStorageProvider(this) { energy }
}

fun <S : StorageStack<S>> IStorageComponent<S>.powered(energy: Supplier<IMatteryEnergyStorage>): IStorageComponent<S> {
	return PoweredComponent(this, energy)
}

fun <S : StorageStack<S>> IStorageComponent<S>.powered(energy: IMatteryEnergyStorage): IStorageComponent<S> {
	return PoweredComponent(this) { energy }
}

fun <S : StorageStack<S>> IVirtualStorageComponent<S>.powered(energy: Supplier<IMatteryEnergyStorage>): IVirtualStorageComponent<S> {
	return PoweredVirtualComponent(this, energy)
}

fun <S : StorageStack<S>> IVirtualStorageComponent<S>.powered(energy: IMatteryEnergyStorage): IVirtualStorageComponent<S> {
	return PoweredVirtualComponent(this) { energy }
}

fun <S : StorageStack<S>> IStorageComponent<S>.flow(flow: Supplier<FlowDirection>): IStorageComponent<S> {
	return FlowControlComponent(this, flow)
}

fun <S : StorageStack<S>> IStorageComponent<S>.flow(flow: FlowDirection): IStorageComponent<S> {
	return FlowControlComponent(this) { flow }
}
