//package net.pokeranalytics.android.model.realm
//
//import io.realm.RealmObject
//import io.realm.RealmQuery
//import io.realm.RealmResults
//import io.realm.annotations.Ignore
//import io.realm.annotations.LinkingObjects
//import net.pokeranalytics.android.exceptions.ModelException
//import timber.log.Timber
//import java.util.*
//
//open class TimeFrame : RealmObject() {
//
//    // A start date
//    var startDate: Date = Date()
//        private set(value) {
//            field = value
//            this.computeNetDuration()
//        }
//
//    // An end date
//    var endDate: Date? = null
//        private set(value) {
//            field = value
//            this.computeNetDuration()
//        }
//
//    // The latest pause date
//    var pauseDate: Date? = null
//        set(value) {
//            field?.let {
//                if (value == null && field != null) {
//                    breakDuration += Date().time - it.time
//                }
//            }
//            field = value
//            this.computeNetDuration()
//        }
//
//    // The break netDuration
//    var breakDuration: Long = 0L
//        set(value) {
//            field = value
//            this.computeNetDuration()
//        }
//
//    // the total netDuration
//    var netDuration: Long = 0L
//        private set
//
//    var hourlyDuration: Double = 0.0
//        get() {
//            return this.netDuration / 3600000.0 // 3.6 millions of milliseconds
//        }
//
//    // Session
//    @LinkingObjects("timeFrame")
//    private val endedSessions: RealmResults<Session>? = null // we should have only one session
//
//    @Ignore
//    var session: Session? = null
//        get() = if (this.endedSessions != null && this.endedSessions.isEmpty()) null else this.endedSessions?.first()
//
//    // Group
//    @LinkingObjects("timeFrame")
//    private val sets: RealmResults<SessionSet>? = null // we should have only one sessionGroup
//
//    @Ignore
//    var set: SessionSet? = null
//        get() = this.sets?.first()
//
//    fun setStart(startDate: Date) {
//        this.startDate = startDate
//        this.session?.let {
//            this.notifySessionDateChange(it)
//        }
//    }
//
//    fun setEnd(endDate: Date?) {
//        this.endDate = endDate
//        this.session?.let {
//            this.notifySessionDateChange(it)
//        }
//    }
//
//    fun setDate(startDate: Date, endDate: Date?) {
//        this.startDate = startDate
//        this.endDate = endDate
//
//        this.session?.let {
//            this.notifySessionDateChange(it)
//        }
//    }
//
//    /**
//     * Computes the net netDuration of the session
//     */
//    private fun computeNetDuration() {
//        var endDate: Date = this.endDate ?: Date()
//        this.netDuration = endDate.time - this.startDate.time - this.breakDuration
//    }
//
//    /**
//     * Queries all time frames that might be impacted by the date change
//     * Makes all necessary changes to keep sequential time frames
//     */
//    fun notifySessionDateChange(owner: Session) {
//
//        var query: RealmQuery<SessionSet> = this.realm.where(SessionSet::class.java)
//        query.isNotNull("timeFrame")
//
////        Timber.d("this> sd = : ${this.startDate}, ed = ${this.endDate}")
//
//        val sets = realm.where(SessionSet::class.java).findAll()
////        Timber.d("set count = ${sets.size}")
//
//        if (this.endDate == null) {
//            query.greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
//                .or()
//                .greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
//                .or()
//                .isNull("timeFrame.endDate")
//        } else {
//            val endDate = this.endDate!!
//            query
//                .lessThanOrEqualTo("timeFrame.startDate", this.startDate)
//                .greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
//                .or()
//                .lessThanOrEqualTo("timeFrame.startDate", endDate)
//                .greaterThanOrEqualTo("timeFrame.endDate", endDate)
//                .or()
//                .greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
//                .lessThanOrEqualTo("timeFrame.endDate", endDate)
//                .or()
//                .isNull("timeFrame.endDate")
//                .lessThanOrEqualTo("timeFrame.startDate", endDate)
//        }
//
//        val sessionGroups = query.findAll()
//
//        this.updateTimeFrames(sessionGroups, owner)
//
//    }
//
//    /**
//     * Update Time frames from sets
//     */
//    private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, owner: Session) {
//
//        when (sessionSets.size) {
//            0 -> this.createOrUpdateSessionSet(owner)
//            1 -> this.updateSessionGroup(owner, sessionSets.first()!!)
//            else -> this.mergeSessionGroups(owner, sessionSets)
//        }
//
//    }
//
//    /**
//     * Creates the session sessionGroup when the session has none
//     */
//    private fun createOrUpdateSessionSet(owner: Session) {
//
//        val set = owner.sessionSet
//        if (set != null) {
//            set.timeFrame?.startDate = this.startDate
//            set.timeFrame?.endDate = this.endDate
//        } else {
//            this.createSessionSet(owner)
//        }
//
////        Timber.d("sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}")
//        Timber.d("netDuration 1 = : ${set?.timeFrame?.netDuration}")
//
//    }
//
//    fun createSessionSet(owner: Session) {
//        val set: SessionSet = SessionSet.newInstanceForResult(this.realm)
//        set.timeFrame?.let {
//            it.startDate = this.startDate
//            it.endDate = this.endDate
//        } ?: run {
//            throw ModelException("TimeFrame should never be null here")
//        }
//
//        owner.sessionSet = set
//    }
//
//
//    /**
//     * Single SessionSet update, the session might be the owner
//     * Changes the sessionGroup timeframe using the current timeframe dates
//     */
//    private fun updateSessionGroup(owner: Session, sessionSet: SessionSet) {
//
//        var timeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query
////        timeFrame.setDate(this.startDate, this.endDate)
//
//        val sisterSessions = sessionSet.endedSessions!! // shouldn't crash ever
//
//        // if we have only one session in the set and that it corresponds to the set
//        if (sessionSet.endedSessions?.size == 1 && sessionSet.endedSessions?.first() == owner) {
//            timeFrame.setDate(this.startDate, this.endDate)
//        } else { // there are 2+ endedSessions to manage and possible splits
//
//            val endDate = this.endDate
//
//            // case where all endedSessions are over but the set is not, we might have a split, so we delete the set and save everything again
//            if (endDate != null && sisterSessions.all { it.timeFrame?.endDate != null } && timeFrame.endDate == null) {
//                var endedSessions = mutableListOf<Session>(owner)
//                sessionSet.endedSessions?.forEach { endedSessions.add(it) }
//                sessionSet.deleteFromRealm()
//                endedSessions.forEach { it.timeFrame?.notifySessionDateChange(it) }
//            } else {
//
//                if (this.startDate.before(timeFrame.startDate)) {
//                    timeFrame.startDate = this.startDate
//                }
//                if (endDate != null && timeFrame.endDate != null && endDate.after(timeFrame.endDate)) {
//                    timeFrame.endDate = endDate
//                } else if (endDate == null) {
//                    timeFrame.endDate = null
//                }
//
//                owner.sessionSet = sessionSet
//
////                Timber.d("sd = : ${sessionSet.timeFrame?.startDate}, ed = ${sessionSet.timeFrame?.endDate}")
//                Timber.d("netDuration 2 = : ${sessionSet.timeFrame?.netDuration}")
//            }
//
//        }
//
//    }
//
//    /**
//     * Multiple session sets update:
//     * Merges all sets into one (delete all then create a new one)
//     */
//    private fun mergeSessionGroups(owner: Session, sessionSets: RealmResults<SessionSet>) {
//
//        var startDate: Date = this.startDate
//        var endDate: Date? = this.endDate
//
//        // find earlier and later dates from all sets
//        val timeFrames = sessionSets.mapNotNull { it.timeFrame }
//        timeFrames.forEach { tf ->
//            if (tf.startDate.before(startDate)) {
//                startDate = tf.startDate
//            }
//
//            endDate?.let { ed ->
//                tf.endDate?.let { tfed ->
//                    if (tfed.after(ed)) {
//                        endDate = tfed
//                    }
//                }
//            } ?: run {
//                endDate = tf.endDate
//            }
//
//        }
//
//        // get all endedSessions from sets
//        var endedSessions = mutableSetOf<Session>()
//        sessionSets.forEach { set ->
//            set.endedSessions?.asIterable()?.let { endedSessions.addAll(it) }
//        }
//
//        // delete all sets
//        sessionSets.deleteAllFromRealm()
//
//        // Create a new sets
//        val set: SessionSet = SessionSet.newInstanceForResult(this.realm)
//        set.timeFrame?.let {
//            it.setDate(startDate, endDate)
//        } ?: run {
//            throw ModelException("TimeFrame should never be null here")
//        }
//
//        // Add the session linked to this timeframe to the new sessionGroup
//        owner.sessionSet = set
//
//        // Add all orphan endedSessions
//        endedSessions.forEach { it.sessionSet = set }
//        Timber.d("netDuration 3 = : ${set.timeFrame?.netDuration}")
//
//    }
//
//}
