package ru.annin.phitoled.presentation.ui.decoration

import android.support.v7.widget.RecyclerView
import android.util.SparseArray
import java.util.*

/**
 * https://gist.github.com/jpshelley/4e0d4aa16c20e91a6c01e48d278b4282
 *
 * @author Pavel Annin.
 */

/**
 * A section to use in Recycler Adapter's.
 * It holds a sectioned position for use in determining the offset of the adapter items.
 */
data class AdapterSection(var firstPosition: Int, var title: String, var sectionedPosition: Int = 0)

/**
 * An adapter that allows a RecyclerView to contain sections or subheaders
 * much like the material docs describe.
 * https://material.google.com/components/subheaders.html
 */
interface SectionedAdapter {

    /** A list of sections to display in adapter. */
    var sections: SparseArray<AdapterSection>

    /** Returns true if the given position contains a section */
    fun isSectionHeaderPosition(position: Int) = sections[position] != null

    /** Determines the correct position based off of the number of currently displayed sections. */
    fun sectionedPositionToPosition(sectionedPosition: Int): Int {
        if (isSectionHeaderPosition(sectionedPosition)) {
            return RecyclerView.NO_POSITION
        }

        var offset = 0
        for (i in 0..sections.size() - 1) {
            if (sections.valueAt(i).sectionedPosition > sectionedPosition) {
                break
            }
            --offset
        }
        return sectionedPosition + offset
    }

    fun positionToSectionedPosition(position: Int): Int {
        var offset = 0
        for (i in 0..sections.size() - 1) {
            if (sections.valueAt(i).firstPosition > position) {
                break
            }
            ++offset
        }
        return position + offset
    }

    /**
     * Clears the current set of selections and sets a new list.
     * In order for the new sections to be displayed, one must first call
     * notifyDatasetChanged()
     *
     * @param newSections The new sections to be set
     */
    fun setSections(newSections: Array<AdapterSection>) {
        sections.clear()
        val sortedSections = newSections.clone()
        Arrays.sort<AdapterSection>(sortedSections) { o, o1 ->
            when {
                o.firstPosition == o1.firstPosition -> 0
                o.firstPosition < o1.firstPosition -> -1
                else -> 1
            }
        }

        var offset = 0 // offset positions for the headers we're adding
        sortedSections.forEach {
            it.sectionedPosition = it.firstPosition + offset
            sections.append(it.sectionedPosition, it)
            ++offset
        }
    }


    /** Returns the nearest section header if one exists */
    tailrec fun getNearestSectionHeader(sectionedPosition: Int): Int {
        if (isSectionHeaderPosition(sectionedPosition)) {
            return sectionedPosition
        } else {
            return getNearestSectionHeader(sectionedPosition - 1)
        }
    }
}