/*
 * Copyright lt 2023
 *
 * 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 com.lt.compose_views.banner

import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.interaction.DragInteraction
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import com.lt.compose_views.compose_pager.*
import com.lt.compose_views.util.DragInteractionSource
import kotlinx.coroutines.delay

/**
 * creator: lt  2022/6/25  lt.dygzs@qq.com
 * effect : 可以自动循环轮播的ComposePager
 *          [ComposePager] that can auto scroll
 * warning:
 * @param pageCount 一共有多少页
 *                  Sum page count
 * @param modifier 修饰
 * @param bannerState Banner的状态
 *                    Banner's state
 * @param orientation 滑动的方向
 *                    Scroll orientation
 * @param userEnable 用户是否可以滑动,等于false时用户滑动无反应,但代码可以执行翻页
 *                   Whether the user can scroll
 * @param autoScroll 是否自动滚动
 *                   Whether to scroll automatically
 * @param autoScrollTime 自动滚动间隔时间
 *                       Auto scroll interval
 * @param bannerKey 使用key来提高性能,减少重组,效果等同于[LazyColumn#items#key]
 *                  Using key to improve performance, reduce recombination, and achieve the same effect as [LazyColumn#items#key]
 * @param clip 是否对内容区域进行裁剪
 *             Whether to crop the content area
 * @param contentTransformation 变换ComposePager的Content
 *                              Transform the Content of ComposePager
 * @param content compose内容区域
 *                Content of compose
 */
@Composable
fun Banner(
    pageCount: Int,
    modifier: Modifier = Modifier,
    bannerState: BannerState = rememberBannerState(),
    orientation: Orientation = Orientation.Horizontal,
    userEnable: Boolean = true,
    autoScroll: Boolean = true,
    autoScrollTime: Long = 3000,
    bannerKey: (index: Int) -> Any = { it },
    clip: Boolean = true,
    contentTransformation: PagerContentTransformation = NoPagerContentTransformation,
    content: @Composable BannerScope.() -> Unit,
) {
    if (pageCount <= 0)
        return
    //是否正在滚动倒计时中
    var scrolling by remember(key1 = autoScroll, key2 = pageCount) {
        mutableStateOf(autoScroll && pageCount > 1)
    }
    val scrollableInteractionSource = remember(key1 = autoScroll, key2 = pageCount) {
        if (!autoScroll)
            return@remember null
        if (pageCount <= 1) {
            scrolling = false
            return@remember null
        }
        DragInteractionSource { interaction ->
            scrolling = interaction !is DragInteraction.Start
        }
    }
    //计算总共多少页
    val maxPageCount = remember(pageCount) {
        bannerState.pageCount = pageCount
        bannerState.composePagerState.setPageIndex(pageCount * bannerState.startMultiple)
        minOf(pageCount * bannerState.sumMultiple, Int.MAX_VALUE)
    }

    //自动滚动
    if (scrolling)
        LaunchedEffect(key1 = autoScrollTime, block = {
            while (true) {
                delay(autoScrollTime)
                val index = bannerState.composePagerState.getCurrSelectIndex()
                if (index + 1 >= maxPageCount)
                    bannerState.composePagerState.setPageIndex(pageCount * bannerState.startMultiple)
                else
                    bannerState.composePagerState.setPageIndexWithAnimate(index + 1)
            }
        })

    CompositionLocalProvider(LocalIndexToKey provides { it % pageCount }) {
        //使用ComposePager放置元素
        ComposePager(
            pageCount = maxPageCount,
            modifier = modifier,
            composePagerState = bannerState.composePagerState,
            orientation = orientation,
            userEnable = userEnable,
            pageCache = maxOf(2, (pageCount - 1) / 2),
            scrollableInteractionSource = scrollableInteractionSource,
            pagerKey = bannerKey,
            clip = clip,
            contentTransformation = contentTransformation,
        ) {
            content(BannerScope(index))
        }
    }
}