package app.furmeet.events.system.schedule.abstractDataTypes

import app.furmeet.events.system.helper.formatAsIso
import java.io.Serializable
import java.util.*

class GregorianCalendarRange(val start: GregorianCalendar, val finish: GregorianCalendar) : Serializable {
    constructor(start: Long, finish: Long) :
            this(
                    GregorianCalendar().apply { timeInMillis = start },
                    GregorianCalendar().apply { timeInMillis = finish }
            )

    init {
        assert(start <= finish)
    }
//    .private fun overlaps(that: GregorianCalendarRange) =
//            ((this.start  >= that.start) and (this.start  <= that.finish)) or
//            ((this.finish >= that.start) and (this.finish <= that.finish)) or
//            ((that.start  >= this.start) and (that.start  <= this.finish)) or
//            ((that.finish >= this.start) and (that.finish <= this.finish))
//
//    .operator fun contains(date: GregorianCalendar) = (start<=date) and (finish>=date)
//    .operator fun contains(range: GregorianCalendarRange) = overlaps(range)

    operator fun contains(date: GregorianCalendar) = (start <= date) and (finish > date)

    operator fun contains(that: GregorianCalendarRange): Boolean =
            ((this.start >= that.start) and (this.start < that.finish)) or
                    ((this.finish > that.start) and (this.finish < that.finish)) or
                    ((that.start >= this.start) and (that.start < this.finish)) or
                    ((that.finish > this.start) and (that.finish < this.finish))

    override fun hashCode(): Int = start.hashCode() xor finish.hashCode()
    override fun equals(other: Any?): Boolean =
            when (other) {
                null -> false
                is GregorianCalendarRange -> {
                    ((this.start.timeInMillis == other.start.timeInMillis) and (this.finish.timeInMillis == other.finish.timeInMillis))
                }
                else -> false
            }

    fun split(parts: Int): List<GregorianCalendarRange> {
        if (parts <= 1) return listOf(this)
        val start = (this.start.timeInMillis)
        val duration = (this.finish.timeInMillis) - (this.start.timeInMillis)
        val durationSegment = duration / parts
        return (1..parts).map {
            Pair(
                    start + (durationSegment * (it - 1)),
                    start + (durationSegment * it)
            )
        }.map {
            GregorianCalendarRange(
                    GregorianCalendar().apply { timeInMillis = it.first },
                    GregorianCalendar().apply { timeInMillis = it.second }
            )
        }
    }

    override fun toString(): String {
        return "${this::class.java.simpleName}(${start.timeInMillis.formatAsIso()} --> ${finish.timeInMillis.formatAsIso()})"
    }
}