/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.compose.foundation.lazy.staggeredgrid

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
import androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridLaneInfo.Companion.FullSpan
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridLaneInfo.Companion.Unset
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.constrainHeight
import androidx.compose.ui.unit.constrainWidth
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.fastForEachIndexed
import androidx.compose.ui.util.fastForEachReversed
import androidx.compose.ui.util.fastMaxOfOrNull
import androidx.compose.ui.util.packInts
import androidx.compose.ui.util.unpackInt1
import androidx.compose.ui.util.unpackInt2
import kotlin.math.abs
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.math.sign
import kotlinx.coroutines.CoroutineScope

private const val DebugLoggingEnabled = false

@ExperimentalFoundationApi
private inline fun <T> withDebugLogging(
    scope: LazyLayoutMeasureScope,
    block: LazyLayoutMeasureScope.() -> T
): T {
    val result = if (DebugLoggingEnabled) {
        try {
            println("╭──────{ measure start }───────────")
            with(scope, block)
        } finally {
            println("╰──────{ measure done }────────────")
        }
    } else {
        with(scope, block)
    }
    return result
}

private fun Array<ArrayDeque<LazyStaggeredGridMeasuredItem>>.debugRender(): String =
    if (DebugLoggingEnabled) {
        @Suppress("ListIterator")
        map { items -> items.map { it.index } }.toString()
    } else {
        ""
    }

private inline fun debugLog(message: () -> String) {
    if (DebugLoggingEnabled) {
        println("│ - ${message()}")
    }
}

@ExperimentalFoundationApi
internal fun LazyLayoutMeasureScope.measureStaggeredGrid(
    state: LazyStaggeredGridState,
    pinnedItems: List<Int>,
    itemProvider: LazyStaggeredGridItemProvider,
    resolvedSlots: LazyStaggeredGridSlots,
    constraints: Constraints,
    isVertical: Boolean,
    reverseLayout: Boolean,
    contentOffset: IntOffset,
    mainAxisAvailableSize: Int,
    mainAxisSpacing: Int,
    beforeContentPadding: Int,
    afterContentPadding: Int,
    coroutineScope: CoroutineScope,
): LazyStaggeredGridMeasureResult {
    val context = LazyStaggeredGridMeasureContext(
        state = state,
        pinnedItems = pinnedItems,
        itemProvider = itemProvider,
        resolvedSlots = resolvedSlots,
        constraints = constraints,
        isVertical = isVertical,
        contentOffset = contentOffset,
        mainAxisAvailableSize = mainAxisAvailableSize,
        beforeContentPadding = beforeContentPadding,
        afterContentPadding = afterContentPadding,
        reverseLayout = reverseLayout,
        mainAxisSpacing = mainAxisSpacing,
        measureScope = this,
        coroutineScope = coroutineScope
    )

    val initialItemIndices: IntArray
    val initialItemOffsets: IntArray

    Snapshot.withoutReadObservation {
        // ensure scroll position is up to date
        val firstVisibleIndices =
            state.updateScrollPositionIfTheFirstItemWasMoved(
                itemProvider,
                state.scrollPosition.indices
            )
        val firstVisibleOffsets = state.scrollPosition.scrollOffsets

        initialItemIndices =
            if (firstVisibleIndices.size == context.laneCount) {
                firstVisibleIndices
            } else {
                // Grid got resized (or we are in a initial state)
                // Adjust indices accordingly
                context.laneInfo.reset()
                IntArray(context.laneCount).apply {
                    // Try to adjust indices in case grid got resized
                    for (lane in indices) {
                        this[lane] = if (
                            lane < firstVisibleIndices.size && firstVisibleIndices[lane] != Unset
                        ) {
                            firstVisibleIndices[lane]
                        } else {
                            if (lane == 0) {
                                0
                            } else {
                                maxInRange(SpanRange(0, lane)) + 1
                            }
                        }
                        // Ensure spans are updated to be in correct range
                        context.laneInfo.setLane(this[lane], lane)
                    }
                }
            }
        initialItemOffsets =
            if (firstVisibleOffsets.size == context.laneCount) {
                firstVisibleOffsets
            } else {
                // Grid got resized (or we are in a initial state)
                // Adjust offsets accordingly
                IntArray(context.laneCount).apply {
                    // Adjust offsets to match previously set ones
                    for (lane in indices) {
                        this[lane] = if (lane < firstVisibleOffsets.size) {
                            firstVisibleOffsets[lane]
                        } else {
                            if (lane == 0) 0 else this[lane - 1]
                        }
                    }
                }
            }
    }

    return context.measure(
        initialScrollDelta = state.scrollToBeConsumed.roundToInt(),
        initialItemIndices = initialItemIndices,
        initialItemOffsets = initialItemOffsets,
        canRestartMeasure = true,
    )
}

@OptIn(ExperimentalFoundationApi::class)
internal class LazyStaggeredGridMeasureContext(
    val state: LazyStaggeredGridState,
    val pinnedItems: List<Int>,
    val itemProvider: LazyStaggeredGridItemProvider,
    val resolvedSlots: LazyStaggeredGridSlots,
    val constraints: Constraints,
    val isVertical: Boolean,
    val measureScope: LazyLayoutMeasureScope,
    val mainAxisAvailableSize: Int,
    val contentOffset: IntOffset,
    val beforeContentPadding: Int,
    val afterContentPadding: Int,
    val reverseLayout: Boolean,
    val mainAxisSpacing: Int,
    val coroutineScope: CoroutineScope
) {
    val measuredItemProvider = object : LazyStaggeredGridMeasureProvider(
        isVertical = isVertical,
        itemProvider = itemProvider,
        measureScope = measureScope,
        resolvedSlots = resolvedSlots,
    ) {
        override fun createItem(
            index: Int,
            lane: Int,
            span: Int,
            key: Any,
            contentType: Any?,
            placeables: List<Placeable>
        ) = LazyStaggeredGridMeasuredItem(
            index = index,
            key = key,
            placeables = placeables,
            isVertical = isVertical,
            spacing = mainAxisSpacing,
            lane = lane,
            span = span,
            beforeContentPadding = beforeContentPadding,
            afterContentPadding = afterContentPadding,
            contentType = contentType,
            animator = state.placementAnimator
        )
    }

    val laneInfo = state.laneInfo

    val laneCount = resolvedSlots.sizes.size

    fun LazyStaggeredGridItemProvider.isFullSpan(itemIndex: Int): Boolean =
        spanProvider.isFullSpan(itemIndex)

    fun LazyStaggeredGridItemProvider.getSpanRange(itemIndex: Int, lane: Int): SpanRange {
        val isFullSpan = spanProvider.isFullSpan(itemIndex)
        val span = if (isFullSpan) laneCount else 1
        val targetLane = if (isFullSpan) 0 else lane
        return SpanRange(targetLane, span)
    }

    inline val SpanRange.isFullSpan: Boolean
        get() = size != 1

    inline val SpanRange.laneInfo: Int
        get() = if (isFullSpan) FullSpan else start
}

@ExperimentalFoundationApi
private fun LazyStaggeredGridMeasureContext.measure(
    initialScrollDelta: Int,
    initialItemIndices: IntArray,
    initialItemOffsets: IntArray,
    canRestartMeasure: Boolean,
): LazyStaggeredGridMeasureResult {
    withDebugLogging(measureScope) {
        val itemCount = itemProvider.itemCount

        if (itemCount <= 0 || laneCount == 0) {
            return LazyStaggeredGridMeasureResult(
                firstVisibleItemIndices = initialItemIndices,
                firstVisibleItemScrollOffsets = initialItemOffsets,
                consumedScroll = 0f,
                measureResult = layout(constraints.minWidth, constraints.minHeight) {},
                canScrollForward = false,
                isVertical = isVertical,
                visibleItemsInfo = emptyList(),
                remeasureNeeded = false,
                totalItemsCount = itemCount,
                viewportSize = IntSize(constraints.minWidth, constraints.minHeight),
                viewportStartOffset = -beforeContentPadding,
                viewportEndOffset = mainAxisAvailableSize + afterContentPadding,
                beforeContentPadding = beforeContentPadding,
                afterContentPadding = afterContentPadding,
                mainAxisItemSpacing = mainAxisSpacing
            )
        }

        // represents the real amount of scroll we applied as a result of this measure pass.
        var scrollDelta = initialScrollDelta

        val firstItemIndices = initialItemIndices.copyOf()
        val firstItemOffsets = initialItemOffsets.copyOf()

        // will be set to true if we composed some items only to know their size and apply scroll,
        // while in the end this item will not end up in the visible viewport. we will need an
        // extra remeasure in order to dispose such items.
        var remeasureNeeded = false

        // update spans in case item count is lower than before
        ensureIndicesInRange(firstItemIndices, itemCount)

        // applying the whole requested scroll offset. we will figure out if we can't consume
        // all of it later
        firstItemOffsets.offsetBy(-scrollDelta)

        // this will contain all the MeasuredItems representing the visible items
        val measuredItems = Array(laneCount) {
            ArrayDeque<LazyStaggeredGridMeasuredItem>(16)
        }

        // include the start padding so we compose items in the padding area. before starting
        // scrolling forward we would remove it back
        firstItemOffsets.offsetBy(-beforeContentPadding)

        fun hasSpaceBeforeFirst(): Boolean {
            for (lane in firstItemIndices.indices) {
                val itemIndex = firstItemIndices[lane]
                val itemOffset = firstItemOffsets[lane]

                if (itemOffset < maxOf(-mainAxisSpacing, 0) && itemIndex > 0) {
                    return true
                }
            }

            return false
        }

        debugLog {
            "up from indices: ${firstItemIndices.toList()}, offsets: ${firstItemOffsets.toList()}"
        }

        var laneToCheckForGaps = -1

        // we had scrolled backward or we compose items in the start padding area, which means
        // items before current firstItemOffset should be visible. compose them and update
        // firstItemOffsets
        while (hasSpaceBeforeFirst()) {
            // staggered grid always keeps item index increasing top to bottom
            // the first item that should contain something before it must have the largest index
            // among the rest
            val laneIndex = firstItemIndices.indexOfMaxValue()
            val itemIndex = firstItemIndices[laneIndex]

            // other lanes might have smaller offsets than the one chosen above, which indicates
            // incorrect measurement (e.g. item was deleted or it changed size)
            // correct this by offsetting affected lane back to match currently chosen offset
            for (i in firstItemOffsets.indices) {
                if (
                    firstItemIndices[i] != firstItemIndices[laneIndex] &&
                        firstItemOffsets[i] < firstItemOffsets[laneIndex]
                ) {
                    // If offset of the lane is smaller than currently chosen lane,
                    // offset the lane to be where current value of the chosen index is.
                    firstItemOffsets[i] = firstItemOffsets[laneIndex]
                }
            }

            val previousItemIndex = findPreviousItemIndex(itemIndex, laneIndex)
            if (previousItemIndex < 0) {
                laneToCheckForGaps = laneIndex
                break
            }

            val spanRange = itemProvider.getSpanRange(previousItemIndex, laneIndex)
            laneInfo.setLane(previousItemIndex, spanRange.laneInfo)
            val measuredItem = measuredItemProvider.getAndMeasure(
                index = previousItemIndex,
                span = spanRange
            )

            val offset = firstItemOffsets.maxInRange(spanRange)
            val gaps = if (spanRange.isFullSpan) laneInfo.getGaps(previousItemIndex) else null
            spanRange.forEach { lane ->
                firstItemIndices[lane] = previousItemIndex
                val gap = if (gaps == null) 0 else gaps[lane]
                val newOffset = offset + measuredItem.sizeWithSpacings + gap
                firstItemOffsets[lane] = newOffset
                // newOffset here is negative. if this item will not be inside of the viewport
                // this means we composed this item, but will not need it.
                if (mainAxisAvailableSize + newOffset <= 0) {
                    remeasureNeeded = true
                }
            }
        }
        debugLog {
            "up done. measured items: ${measuredItems.debugRender()}"
        }

        fun misalignedStart(referenceLane: Int): Boolean {
            // If we scrolled past the first item in the lane, we have a point of reference
            // to re-align items.

            // Case 1: Each lane has laid out all items, but offsets do no match
            for (lane in firstItemIndices.indices) {
                val misalignedOffsets =
                    findPreviousItemIndex(firstItemIndices[lane], lane) == Unset &&
                        firstItemOffsets[lane] != firstItemOffsets[referenceLane]

                if (misalignedOffsets) {
                    return true
                }
            }
            // Case 2: Some lanes are still missing items, and there's no space left to place them
            for (lane in firstItemIndices.indices) {
                val moreItemsInOtherLanes =
                    findPreviousItemIndex(firstItemIndices[lane], lane) != Unset &&
                        firstItemOffsets[lane] >= firstItemOffsets[referenceLane]

                if (moreItemsInOtherLanes) {
                    return true
                }
            }
            // Case 3: the first item is in the wrong lane (it should always be in
            // the first one)
            val firstItemLane = laneInfo.getLane(0)
            return firstItemLane != 0 && firstItemLane != Unset && firstItemLane != FullSpan
        }

        // define min offset (currently includes beforeContentPadding)
        val minOffset = -beforeContentPadding

        // we scrolled backward, but there were not enough items to fill the start. this means
        // some amount of scroll should be left over
        if (firstItemOffsets[0] < minOffset) {
            scrollDelta += firstItemOffsets[0]
            firstItemOffsets.offsetBy(minOffset - firstItemOffsets[0])
            debugLog {
                "up, correcting scroll delta from ${firstItemOffsets[0]} to $minOffset"
            }
        }

        // neutralize previously added start padding as we stopped filling the before content padding
        firstItemOffsets.offsetBy(beforeContentPadding)

        laneToCheckForGaps =
            if (laneToCheckForGaps == -1) firstItemIndices.indexOf(0) else laneToCheckForGaps

        // re-check if columns are aligned after measure
        if (laneToCheckForGaps != -1) {
            val lane = laneToCheckForGaps
            if (misalignedStart(lane) && canRestartMeasure) {
                laneInfo.reset()
                return measure(
                    initialScrollDelta = scrollDelta,
                    initialItemIndices = IntArray(firstItemIndices.size) { -1 },
                    initialItemOffsets = IntArray(firstItemOffsets.size) {
                        firstItemOffsets[lane]
                    },
                    canRestartMeasure = false
                )
            }
        }

        // start measuring down from first item indices/offsets decided above to ensure correct
        // arrangement.
        // this means we are calling measure second time on items previously measured in this
        // function, but LazyLayout caches them, so no overhead.
        val currentItemIndices = firstItemIndices.copyOf()
        val currentItemOffsets = IntArray(firstItemOffsets.size) {
            -firstItemOffsets[it]
        }

        val minVisibleOffset = minOffset + mainAxisSpacing
        val maxOffset = (mainAxisAvailableSize + afterContentPadding).coerceAtLeast(0)

        debugLog {
            "down current, indices: ${currentItemIndices.toList()}, " +
                "offsets: ${currentItemOffsets.toList()}"
        }

        // current item should be pointing to the index of previously measured item below,
        // as lane assignments must be decided based on size and offset of all previous items
        // this loop makes sure to measure items that were initially passed to the current item
        // indices with correct item order
        var initialItemsMeasured = 0
        var initialLaneToMeasure = currentItemIndices.indexOfMinValue()
        while (initialLaneToMeasure != -1 && initialItemsMeasured < laneCount) {
            val itemIndex = currentItemIndices[initialLaneToMeasure]
            val laneIndex = initialLaneToMeasure

            initialLaneToMeasure = currentItemIndices.indexOfMinValue(minBound = itemIndex)
            initialItemsMeasured++

            if (itemIndex < 0) continue

            val spanRange = itemProvider.getSpanRange(itemIndex, laneIndex)
            val measuredItem = measuredItemProvider.getAndMeasure(
                itemIndex,
                spanRange
            )

            laneInfo.setLane(itemIndex, spanRange.laneInfo)
            val offset = currentItemOffsets.maxInRange(spanRange)
            spanRange.forEach { lane ->
                currentItemOffsets[lane] = offset + measuredItem.sizeWithSpacings
                currentItemIndices[lane] = itemIndex
                measuredItems[lane].addLast(measuredItem)
            }

            // item is not visible if both start and end bounds are outside of the visible range.
            if (
                offset < minVisibleOffset && currentItemOffsets[spanRange.start] <= minVisibleOffset
            ) {
                // We scrolled past measuredItem, and it is not visible anymore. We measured it
                // for correct positioning of other items, but there's no need to place it.
                // Mark it as not visible and filter below.
                measuredItem.isVisible = false
                remeasureNeeded = true
            }

            if (spanRange.isFullSpan) {
                // full span items overwrite other slots if we measure it here, so skip measuring
                // the rest of the slots
                initialItemsMeasured = laneCount
            }
        }

        debugLog {
            "current filled, measured: ${measuredItems.debugRender()}"
        }
        debugLog {
            "down from indices: ${currentItemIndices.toList()}, " +
                "offsets: ${currentItemOffsets.toList()}"
        }

        // then composing visible items forward until we fill the whole viewport.
        // we want to have at least one item in measuredItems even if in fact all the items are
        // offscreen, this can happen if the content padding is larger than the available size.
        while (
            currentItemOffsets.any {
                it < maxOffset ||
                    it <= 0 // filling beforeContentPadding area
            } || measuredItems.all { it.isEmpty() }
        ) {
            val currentLaneIndex = currentItemOffsets.indexOfMinValue()
            val previousItemIndex = currentItemIndices.max()
            val itemIndex = previousItemIndex + 1

            if (itemIndex >= itemCount) {
                break
            }

            val spanRange = itemProvider.getSpanRange(itemIndex, currentLaneIndex)

            laneInfo.setLane(itemIndex, spanRange.laneInfo)
            val measuredItem = measuredItemProvider.getAndMeasure(itemIndex, spanRange)

            val offset = currentItemOffsets.maxInRange(spanRange)
            val gaps = if (spanRange.isFullSpan) {
                laneInfo.getGaps(itemIndex) ?: IntArray(laneCount)
            } else {
                null
            }
            spanRange.forEach { lane ->
                if (gaps != null) {
                    gaps[lane] = offset - currentItemOffsets[lane]
                }
                currentItemIndices[lane] = itemIndex
                currentItemOffsets[lane] = offset + measuredItem.sizeWithSpacings
                measuredItems[lane].addLast(measuredItem)
            }
            laneInfo.setGaps(itemIndex, gaps)

            // item is not visible if both start and end bounds are outside of the visible range.
            if (
                offset < minVisibleOffset && currentItemOffsets[spanRange.start] <= minVisibleOffset
            ) {
                // We scrolled past measuredItem, and it is not visible anymore. We measured it
                // for correct positioning of other items, but there's no need to place it.
                // Mark it as not visible and filter below.
                measuredItem.isVisible = false
            }
        }

        debugLog {
            "down done. measured items: ${measuredItems.debugRender()}"
        }

        // some measured items are offscreen, remove them from the list and adjust indices/offsets
        for (laneIndex in measuredItems.indices) {
            val laneItems = measuredItems[laneIndex]

            while (laneItems.size > 1 && !laneItems.first().isVisible) {
                val item = laneItems.removeFirst()
                val gaps = if (item.span != 1) laneInfo.getGaps(item.index) else null
                firstItemOffsets[laneIndex] -=
                    item.sizeWithSpacings + if (gaps == null) 0 else gaps[laneIndex]
            }

            firstItemIndices[laneIndex] = laneItems.firstOrNull()?.index ?: Unset
        }

        if (currentItemIndices.any { it == itemCount - 1 }) {
            currentItemOffsets.offsetBy(-mainAxisSpacing)
        }

        debugLog {
            "removed invisible items: ${measuredItems.debugRender()}"
        }
        debugLog {
            "back up, indices: ${firstItemIndices.toList()}, " +
                "offsets: ${firstItemOffsets.toList()}"
        }

        // we didn't fill the whole viewport with items starting from firstVisibleItemIndex.
        // lets try to scroll back if we have enough items before firstVisibleItemIndex.
        if (currentItemOffsets.all { it < mainAxisAvailableSize }) {
            val maxOffsetLane = currentItemOffsets.indexOfMaxValue()
            val toScrollBack = mainAxisAvailableSize - currentItemOffsets[maxOffsetLane]
            firstItemOffsets.offsetBy(-toScrollBack)
            currentItemOffsets.offsetBy(toScrollBack)

            var gapDetected = false
            while (
                firstItemOffsets.any { it < beforeContentPadding }
            ) {
                // We choose the minimum offset value and try to put items on top.
                // Note that it is different from initial pass up where we selected largest index
                // instead. The reason is that we already distributed items on downward pass and
                // gap would be incorrect if those are moved.
                val laneIndex = firstItemOffsets.indexOfMinValue()

                if (laneIndex != firstItemIndices.indexOfMaxValue()) {
                    // If min offset lane doesn't have largest value, it means items are misaligned.
                    // The correct thing here is to restart measure. We will measure up to the end
                    // and restart measure from there after this pass.
                    gapDetected = true
                }

                val currentIndex =
                    if (firstItemIndices[laneIndex] == -1) {
                        itemCount
                    } else {
                        firstItemIndices[laneIndex]
                    }

                val previousIndex =
                    findPreviousItemIndex(currentIndex, laneIndex)

                if (previousIndex < 0) {
                    if ((gapDetected || misalignedStart(laneIndex)) && canRestartMeasure) {
                        laneInfo.reset()
                        return measure(
                            initialScrollDelta = scrollDelta,
                            initialItemIndices = IntArray(firstItemIndices.size) { -1 },
                            initialItemOffsets = IntArray(firstItemOffsets.size) {
                                firstItemOffsets[laneIndex]
                            },
                            canRestartMeasure = false
                        )
                    }
                    break
                }

                val spanRange = itemProvider.getSpanRange(previousIndex, laneIndex)
                laneInfo.setLane(previousIndex, spanRange.laneInfo)
                val measuredItem = measuredItemProvider.getAndMeasure(
                    index = previousIndex,
                    spanRange
                )

                val offset = firstItemOffsets.maxInRange(spanRange)
                val gaps = if (spanRange.isFullSpan) laneInfo.getGaps(previousIndex) else null
                spanRange.forEach { lane ->
                    if (firstItemOffsets[lane] != offset) {
                        // Some items below fully spanned item don't match it exactly. We skip over,
                        // but this should be corrected through remeasure.
                        gapDetected = true
                    }

                    measuredItems[lane].addFirst(measuredItem)
                    firstItemIndices[lane] = previousIndex
                    val gap = if (gaps == null) 0 else gaps[lane]
                    firstItemOffsets[lane] = offset + measuredItem.sizeWithSpacings + gap
                }
            }

            // If incorrectly offset lanes were detected before, restart measure from the current
            // point. Incorrectly offset items will be redistributed to the correct lanes on the
            // downward pass.
            if (gapDetected && canRestartMeasure) {
                laneInfo.reset()
                return measure(
                    initialScrollDelta = scrollDelta,
                    initialItemIndices = firstItemIndices,
                    initialItemOffsets = firstItemOffsets,
                    canRestartMeasure = false
                )
            }

            scrollDelta += toScrollBack

            val minOffsetLane = firstItemOffsets.indexOfMinValue()
            if (firstItemOffsets[minOffsetLane] < 0) {
                val offsetValue = firstItemOffsets[minOffsetLane]
                scrollDelta += offsetValue
                currentItemOffsets.offsetBy(offsetValue)
                firstItemOffsets.offsetBy(-offsetValue)
            }
        }

        debugLog {
            "measured: ${measuredItems.debugRender()}"
        }
        debugLog {
            "first indices: ${firstItemIndices.toList()}, offsets: ${firstItemOffsets.toList()}"
        }

        // report the amount of pixels we consumed. scrollDelta can be smaller than
        // scrollToBeConsumed if there were not enough items to fill the offered space or it
        // can be larger if items were resized, or if, for example, we were previously
        // displaying the item 15, but now we have only 10 items in total in the data set.
        val consumedScroll = if (
            state.scrollToBeConsumed.roundToInt().sign == scrollDelta.sign &&
            abs(state.scrollToBeConsumed.roundToInt()) >= abs(scrollDelta)
        ) {
            scrollDelta.toFloat()
        } else {
            state.scrollToBeConsumed
        }

        val itemScrollOffsets = firstItemOffsets.copyOf().transform { -it }

        // even if we compose items to fill before content padding we should ignore items fully
        // located there for the state's scroll position calculation (first item + first offset)
        debugLog { "adjusting for content padding" }
        if (beforeContentPadding > mainAxisSpacing) {
            for (laneIndex in measuredItems.indices) {
                val laneItems = measuredItems[laneIndex]
                for (i in laneItems.indices) {
                    val item = laneItems[i]
                    val gaps = laneInfo.getGaps(item.index)
                    val size = item.sizeWithSpacings + if (gaps == null) 0 else gaps[laneIndex]
                    if (
                        i != laneItems.lastIndex &&
                        firstItemOffsets[laneIndex] != 0 &&
                        firstItemOffsets[laneIndex] >= size
                    ) {
                        firstItemOffsets[laneIndex] -= size
                        firstItemIndices[laneIndex] = laneItems[i + 1].index
                    } else {
                        break
                    }
                }
            }
        }

        debugLog {
            "final first indices: ${firstItemIndices.toList()}, " +
                "offsets: ${firstItemOffsets.toList()}"
        }

        // end measure

        // start placement

        val contentPadding = beforeContentPadding + afterContentPadding
        val layoutWidth = if (isVertical) {
            constraints.maxWidth
        } else {
            constraints.constrainWidth(currentItemOffsets.max() + contentPadding)
        }
        val layoutHeight = if (isVertical) {
            constraints.constrainHeight(currentItemOffsets.max() + contentPadding)
        } else {
            constraints.maxHeight
        }

        val mainAxisLayoutSize =
            min(if (isVertical) layoutHeight else layoutWidth, mainAxisAvailableSize).let {
                // The offsets are calculated in [-beforePad; size + afterPad] interval
                // Ensure the layout size used for positioning (and reverse layout calculation)
                // is in the same interval.
                it - beforeContentPadding + afterContentPadding
            }

        var extraItemOffset = itemScrollOffsets[0]
        val extraItemsBefore = calculateExtraItems(
            position = {
                extraItemOffset -= it.sizeWithSpacings
                it.position(
                    mainAxis = extraItemOffset,
                    crossAxis = 0,
                    mainAxisLayoutSize = mainAxisLayoutSize
                )
            },
            filter = { itemIndex ->
                val lane = laneInfo.getLane(itemIndex)
                when (lane) {
                    Unset, FullSpan -> {
                        firstItemIndices.all { it > itemIndex }
                    }
                    else -> {
                        firstItemIndices[lane] > itemIndex
                    }
                }
            },
            beforeVisibleBounds = true
        )

        val visibleItems = calculateVisibleItems(
            measuredItems,
            itemScrollOffsets,
            mainAxisLayoutSize,
        )

        extraItemOffset = itemScrollOffsets[0]
        val extraItemsAfter = calculateExtraItems(
            position = {
                it.position(
                    mainAxis = extraItemOffset,
                    crossAxis = 0,
                    mainAxisLayoutSize = mainAxisLayoutSize
                )
                extraItemOffset += it.sizeWithSpacings
            },
            filter = { itemIndex ->
                if (itemIndex >= itemCount) {
                    return@calculateExtraItems false
                }
                val lane = laneInfo.getLane(itemIndex)
                when (lane) {
                    Unset, FullSpan -> {
                        currentItemIndices.all { it < itemIndex }
                    }
                    else -> {
                        currentItemIndices[lane] < itemIndex
                    }
                }
            },
            beforeVisibleBounds = false
        )

        val positionedItems = mutableListOf<LazyStaggeredGridMeasuredItem>()
        positionedItems.addAll(extraItemsBefore)
        positionedItems.addAll(visibleItems)
        positionedItems.addAll(extraItemsAfter)

        debugLog {
            "positioned: $positionedItems"
        }

        state.placementAnimator.onMeasured(
            consumedScroll = consumedScroll.toInt(),
            layoutWidth = layoutWidth,
            layoutHeight = layoutHeight,
            positionedItems = positionedItems,
            itemProvider = measuredItemProvider,
            isVertical = isVertical,
            laneCount = laneCount,
            coroutineScope = coroutineScope
        )

        // end placement

        // only scroll forward if the last item is not on screen or fully visible
        val canScrollForward = currentItemOffsets.any { it > mainAxisAvailableSize } ||
            currentItemIndices.all { it < itemCount - 1 }

        return LazyStaggeredGridMeasureResult(
            firstVisibleItemIndices = firstItemIndices,
            firstVisibleItemScrollOffsets = firstItemOffsets,
            consumedScroll = consumedScroll,
            measureResult = layout(layoutWidth, layoutHeight) {
                positionedItems.fastForEach { item ->
                    item.place(scope = this, context = this@measure)
                }

                // we attach it during the placement so LazyStaggeredGridState can trigger re-placement
                state.placementScopeInvalidator.attachToScope()
            },
            canScrollForward = canScrollForward,
            isVertical = isVertical,
            visibleItemsInfo = visibleItems,
            remeasureNeeded = remeasureNeeded,
            totalItemsCount = itemCount,
            viewportSize = IntSize(layoutWidth, layoutHeight),
            viewportStartOffset = minOffset,
            viewportEndOffset = maxOffset,
            beforeContentPadding = beforeContentPadding,
            afterContentPadding = afterContentPadding,
            mainAxisItemSpacing = mainAxisSpacing
        )
    }
}

private fun LazyStaggeredGridMeasureContext.calculateVisibleItems(
    measuredItems: Array<ArrayDeque<LazyStaggeredGridMeasuredItem>>,
    itemScrollOffsets: IntArray,
    mainAxisLayoutSize: Int,
): List<LazyStaggeredGridMeasuredItem> {
    val positionedItems = ArrayList<LazyStaggeredGridMeasuredItem>(
        measuredItems.sumOf { it.size }
    )
    while (measuredItems.any { it.isNotEmpty() }) {
        // find the next item to position
        val laneIndex = measuredItems.indexOfMinBy {
            it.firstOrNull()?.index ?: Int.MAX_VALUE
        }
        val item = measuredItems[laneIndex].removeFirst()

        if (item.lane != laneIndex) {
            continue
        }

        val spanRange = SpanRange(item.lane, item.span)
        val mainAxisOffset = itemScrollOffsets.maxInRange(spanRange)
        val crossAxisOffset = resolvedSlots.positions[laneIndex]

        if (item.placeablesCount == 0) {
            // nothing to place, ignore spacings
            continue
        }
        item.position(
            mainAxis = mainAxisOffset,
            crossAxis = crossAxisOffset,
            mainAxisLayoutSize = mainAxisLayoutSize,
        )
        positionedItems += item
        spanRange.forEach { lane ->
            itemScrollOffsets[lane] = mainAxisOffset + item.sizeWithSpacings
        }
    }
    return positionedItems
}

@ExperimentalFoundationApi
private inline fun LazyStaggeredGridMeasureContext.calculateExtraItems(
    position: (LazyStaggeredGridMeasuredItem) -> Unit,
    filter: (itemIndex: Int) -> Boolean,
    beforeVisibleBounds: Boolean
): List<LazyStaggeredGridMeasuredItem> {
    var result: MutableList<LazyStaggeredGridMeasuredItem>? = null

    pinnedItems.fastForEach(beforeVisibleBounds) { index ->
        if (filter(index)) {
            val spanRange = itemProvider.getSpanRange(index, 0)
            if (result == null) {
                result = mutableListOf()
            }
            val measuredItem = measuredItemProvider.getAndMeasure(index, spanRange)
            position(measuredItem)
            result?.add(measuredItem)
        }
    }

    return result ?: emptyList()
}

private inline fun <T> List<T>.fastForEach(reverse: Boolean = false, action: (T) -> Unit) {
    if (reverse) fastForEachReversed(action) else fastForEach(action)
}

@JvmInline
internal value class SpanRange private constructor(val packedValue: Long) {
    constructor(lane: Int, span: Int) : this(packInts(lane, lane + span))

    inline val start get(): Int = unpackInt1(packedValue)
    inline val end get(): Int = unpackInt2(packedValue)
    inline val size get(): Int = end - start
}

private inline fun SpanRange.forEach(block: (Int) -> Unit) {
    for (i in start until end) {
        block(i)
    }
}

private fun IntArray.offsetBy(delta: Int) {
    for (i in indices) {
        this[i] = this[i] + delta
    }
}

private fun IntArray.maxInRange(indexRange: SpanRange): Int {
    var max = Int.MIN_VALUE
    indexRange.forEach {
        max = maxOf(max, this[it])
    }
    return max
}

internal fun IntArray.indexOfMinValue(minBound: Int = Int.MIN_VALUE): Int {
    var result = -1
    var min = Int.MAX_VALUE
    for (i in indices) {
        if (this[i] in (minBound + 1) until min) {
            min = this[i]
            result = i
        }
    }

    return result
}

private inline fun <T> Array<T>.indexOfMinBy(block: (T) -> Int): Int {
    var result = -1
    var min = Int.MAX_VALUE
    for (i in indices) {
        val value = block(this[i])
        if (min > value) {
            min = value
            result = i
        }
    }

    return result
}

private fun IntArray.indexOfMaxValue(): Int {
    var result = -1
    var max = Int.MIN_VALUE
    for (i in indices) {
        if (max < this[i]) {
            max = this[i]
            result = i
        }
    }

    return result
}

private inline fun IntArray.transform(block: (Int) -> Int): IntArray {
    for (i in indices) {
        this[i] = block(this[i])
    }
    return this
}

private fun LazyStaggeredGridMeasureContext.ensureIndicesInRange(
    indices: IntArray,
    itemCount: Int
) {
    // reverse traverse to make sure last items are recorded to the latter lanes
    for (i in indices.indices.reversed()) {
        while (indices[i] >= itemCount || !laneInfo.assignedToLane(indices[i], i)) {
            indices[i] = findPreviousItemIndex(indices[i], i)
        }
        if (indices[i] >= 0) {
            // reserve item for span
            if (!itemProvider.isFullSpan(indices[i])) {
                laneInfo.setLane(indices[i], i)
            }
        }
    }
}

private fun LazyStaggeredGridMeasureContext.findPreviousItemIndex(item: Int, lane: Int): Int =
    laneInfo.findPreviousItemIndex(item, lane)

@OptIn(ExperimentalFoundationApi::class)
internal abstract class LazyStaggeredGridMeasureProvider(
    private val isVertical: Boolean,
    private val itemProvider: LazyStaggeredGridItemProvider,
    private val measureScope: LazyLayoutMeasureScope,
    private val resolvedSlots: LazyStaggeredGridSlots
) {
    private fun childConstraints(slot: Int, span: Int): Constraints {
        // resolved slots contain [offset, size] pair per each slot.
        val crossAxisSize = if (span == 1) {
            resolvedSlots.sizes[slot]
        } else {
            val start = resolvedSlots.positions[slot]
            val endSlot = slot + span - 1
            val end = resolvedSlots.positions[endSlot] + resolvedSlots.sizes[endSlot]
            end - start
        }

        return if (isVertical) {
            Constraints.fixedWidth(crossAxisSize)
        } else {
            Constraints.fixedHeight(crossAxisSize)
        }
    }

    fun getAndMeasure(index: Int, span: SpanRange): LazyStaggeredGridMeasuredItem {
        val key = itemProvider.getKey(index)
        val contentType = itemProvider.getContentType(index)

        val slotCount = resolvedSlots.sizes.size
        val spanStart = span.start.coerceAtMost(slotCount - 1)
        val spanSize = span.size.coerceAtMost(slotCount - spanStart)

        val placeables = measureScope.measure(index, childConstraints(spanStart, spanSize))
        return createItem(
            index,
            spanStart,
            spanSize,
            key,
            contentType,
            placeables
        )
    }

    val keyIndexMap: LazyLayoutKeyIndexMap get() = itemProvider.keyIndexMap

    abstract fun createItem(
        index: Int,
        lane: Int,
        span: Int,
        key: Any,
        contentType: Any?,
        placeables: List<Placeable>
    ): LazyStaggeredGridMeasuredItem
}

internal class LazyStaggeredGridMeasuredItem(
    override val index: Int,
    override val key: Any,
    private val placeables: List<Placeable>,
    val isVertical: Boolean,
    spacing: Int,
    override val lane: Int,
    val span: Int,
    private val beforeContentPadding: Int,
    private val afterContentPadding: Int,
    override val contentType: Any?,
    private val animator: LazyStaggeredGridItemPlacementAnimator
) : LazyStaggeredGridItemInfo {
    var isVisible = true

    val placeablesCount: Int get() = placeables.size

    fun getParentData(index: Int) = placeables[index].parentData

    val mainAxisSize: Int = placeables.fastMaxOfOrNull { placeable ->
        if (isVertical) placeable.height else placeable.width
    } ?: 0

    val sizeWithSpacings: Int = (mainAxisSize + spacing).coerceAtLeast(0)

    val crossAxisSize: Int = placeables.fastMaxOfOrNull {
        if (isVertical) it.width else it.height
    } ?: 0

    private var mainAxisLayoutSize: Int = Unset
    private var minMainAxisOffset: Int = 0
    private var maxMainAxisOffset: Int = 0

    /**
     * True when this item is not supposed to react on scroll delta. for example items being
     * animated away out of the bounds are non scrollable.
     */
    var nonScrollableItem: Boolean = false

    override val size: IntSize = if (isVertical) {
        IntSize(crossAxisSize, mainAxisSize)
    } else {
        IntSize(mainAxisSize, crossAxisSize)
    }
    override var offset: IntOffset = IntOffset.Zero
        private set

    fun position(
        mainAxis: Int,
        crossAxis: Int,
        mainAxisLayoutSize: Int,
    ) {
        this.mainAxisLayoutSize = mainAxisLayoutSize
        minMainAxisOffset = -beforeContentPadding
        maxMainAxisOffset = mainAxisLayoutSize + afterContentPadding
        offset = if (isVertical) {
            IntOffset(crossAxis, mainAxis)
        } else {
            IntOffset(mainAxis, crossAxis)
        }
    }

    val mainAxisOffset get() = if (!isVertical) offset.x else offset.y
    val crossAxisOffset get() = if (isVertical) offset.x else offset.y

    fun place(
        scope: Placeable.PlacementScope,
        context: LazyStaggeredGridMeasureContext
    ) = with(context) {
        require(mainAxisLayoutSize != Unset) { "position() should be called first" }
        with(scope) {
            placeables.fastForEachIndexed { index, placeable ->
                val minOffset = minMainAxisOffset - placeable.mainAxisSize
                val maxOffset = maxMainAxisOffset

                var offset = offset
                val animation = animator.getAnimation(key, index)
                if (animation != null) {
                    val animatedOffset = offset + animation.placementDelta
                    // cancel the animation if current and target offsets are both out of the bounds.
                    if ((offset.mainAxis <= minOffset && animatedOffset.mainAxis <= minOffset) ||
                        (offset.mainAxis >= maxOffset && animatedOffset.mainAxis >= maxOffset)
                    ) {
                        animation.cancelPlacementAnimation()
                    }
                    offset = animatedOffset
                }
                if (reverseLayout) {
                    offset = offset.copy { mainAxisOffset ->
                        mainAxisLayoutSize - mainAxisOffset - placeable.mainAxisSize
                    }
                }
                offset += contentOffset
                placeable.placeRelativeWithLayer(offset)
            }
        }
    }

    fun applyScrollDelta(delta: Int) {
        if (nonScrollableItem) {
            return
        }
        offset = offset.copy { it + delta }
        repeat(placeablesCount) { index ->
            val animation = animator.getAnimation(key, index)
            if (animation != null) {
                animation.rawOffset = animation.rawOffset.copy { mainAxis -> mainAxis + delta }
            }
        }
    }

    private val IntOffset.mainAxis get() = if (isVertical) y else x
    private inline val Placeable.mainAxisSize get() = if (isVertical) height else width
    private inline fun IntOffset.copy(mainAxisMap: (Int) -> Int): IntOffset =
        IntOffset(if (isVertical) x else mainAxisMap(x), if (isVertical) mainAxisMap(y) else y)

    override fun toString(): String =
        if (DebugLoggingEnabled) {
            "{$index at $offset}"
        } else {
            super.toString()
        }
}

private const val Unset = Int.MIN_VALUE
