package net.pokeranalytics.android.util.csv

import io.realm.Realm
import io.realm.RealmModel
import org.apache.commons.csv.CSVRecord

/**
 * The various sources of CSV
 */
enum class DataSource {
	POKER_INCOME,
	POKER_BANKROLL_TRACKER,
	RUNGOOD
}

/**
 * A DataCSVDescriptor produces RealmModel instances for each row
 */
abstract class DataCSVDescriptor<T : RealmModel>(source: DataSource, vararg elements: CSVField) : CSVDescriptor(source, *elements) {

	val realmModels = mutableListOf<RealmModel>()

	abstract fun parseData(realm: Realm, record: CSVRecord): T?

	override fun parse(realm: Realm, record: CSVRecord) {

		val data = this.parseData(realm, record)
		data?.let {
			this.realmModels.add(it)
		}

	}

}

/**
 * A CSVDescriptor describes a CSV format by a source and a list of Fields
 */
abstract class CSVDescriptor(var source: DataSource, vararg elements: CSVField) {

	/**
	 * The CSVField list describing the CSV header format
	 */
	protected var fields: List<CSVField> = listOf()
	/**
	 * The mapping of CSVField with their index in the CSV file
	 */
	protected var fieldMapping: MutableMap<CSVField, Int> = mutableMapOf()

	init {
		if (elements.size > 0) {
			this.fields = elements.toList()
		}
	}

	companion object {
		/**
		 * The list of all managed CSVDescriptors
		 */
		val all: List<CSVDescriptor> =
			listOf(SessionCSVDescriptor.pokerIncomeCash, SessionCSVDescriptor.pokerBankrollTracker, SessionCSVDescriptor.runGoodCashGames, SessionCSVDescriptor.runGoodTournaments)
	}

	/**
	 * Returns whether the [record] matches the CSVDescriptor
	 */
	fun matches(record: CSVRecord): Boolean {

		var count = 0
		val headers = record.toSet()

		this.fields.forEach { field ->

			val index = headers.indexOf(field.header)
			this.fieldMapping[field] = index

			if (index >= 0) {
				count++
			}

		}

		return count == this.fields.size
	}

	/**
	 * Method called when iterating on a CSVRecord
	 */
	abstract fun parse(realm: Realm, record: CSVRecord)

}
