﻿// @Author 空伊伊
// @论坛主页 https://forum.ark.online/home.php?mod=space&uid=113&do=thread&view=me&from=space

/** 版本更改事件名 */
const VERSION_CHANGE = "VERSION_CHANGE"
/** 数据名称 */
const VERSION_DATA_NAME = "VersionCheckData"
/** 检查间隔（毫秒） */
const CHECK_GAP = 10000

@Component
export default class VersionCheck extends Script {

    /** 房间当前的版本（房间被创建时会自动获取一次） */
    private curVersion: number = -1

    protected onStart(): void {
        if (SystemUtil.isServer()) { this.serverInit() }
        if (SystemUtil.isClient()) { this.clientInit() }
    }

    /** 服务端初始化 */
    private serverInit() {
        this.serverGetVersionData()
        // 每隔一段时间检查一次版本
        setInterval(() => {
            this.serverCheckVersion()
        }, CHECK_GAP);
        // 每当玩家进入房间，检查一次版本
        Player.onPlayerAdd.add((player: Player) => {
            this.serverCheckVersion()
        })
    }
    /** 服务端启动，获取一次版本号 */
    private async serverGetVersionData() {
        // 创建默认数据
        let versionData: IVersionCheckData = { version: 1, title: "提示", content: "游戏已更新版本，请退出游戏后重新进入", kickSeconds: 0 }
        const kvData = await DataStorage.asyncGetData(VERSION_DATA_NAME)
        if (kvData.code == DataStorageResultCode.Success) {
            if (kvData.data) {
                versionData = kvData.data as IVersionCheckData
            } else {
                DataStorage.asyncSetData(VERSION_DATA_NAME, versionData)
            }
        }
        this.curVersion = versionData.version
        console.error(`【版本检查】房间创建完毕,获取到版本号:${this.curVersion}`)
    }
    /** 检查版本号是否变动 */
    private async serverCheckVersion() {
        // 版本号没获取到，就先不处理
        if (this.curVersion == -1) {
            console.error(`【版本检查】获取版本号失败！`)
            return
        }
        const kvData = await DataStorage.asyncGetData(VERSION_DATA_NAME)
        if (kvData.data) {
            let versionData = kvData.data as IVersionCheckData
            if (this.curVersion < versionData.version) {
                console.error(`【版本检查】通知房间内所有玩家，版本已更新！`)
                Player.getAllPlayers().forEach((player: Player) => {
                    Event.dispatchToClient(player, VERSION_CHANGE, versionData)
                    if (versionData.kickSeconds > 0) {
                        setTimeout(() => {
                            RoomService.kick(player, `游戏已更新，请重新进入`)
                        }, versionData.kickSeconds * 1000);
                    }
                })
                RoomSettings.enableJoiningMidgame(false)
            }
            console.error(`【版本检查】当前版本号:${this.curVersion}    最新版本号:${versionData.version}`)
        }
    }
    /** 客户端初始化 */
    private clientInit() {
        const tipsUI = new VersionTipsUI()
        tipsUI.hide()
        Event.addServerListener(VERSION_CHANGE, (data: IVersionCheckData) => {
            tipsUI.setContent(data.title, data.content)
            tipsUI.show()
        })
    }
}

/** 版本数据结构 */
interface IVersionCheckData {
    /** 版本号 */
    version: number
    /** 提示UI的标题 */
    title: string
    /** 提示UI的内容 */
    content: string
    /** 几秒后踢出玩家(填0则代表不踢出) */
    kickSeconds: number
}

/**
 * 纯代码编写的提示UI
 */
class VersionTipsUI {
    private uiWidget: UserWidget
    private titleText: TextBlock
    private contentText: TextBlock
    constructor() {
        this.init()
    }
    private init() {
        // 创建UI主体
        this.uiWidget = UserWidget.newObject();
        this.uiWidget.addToViewport(600000)
        this.uiWidget.zOrder = 600000
        this.uiWidget.constraints = new UIConstraintAnchors(UIConstraintHorizontal.LeftRight, UIConstraintVertical.TopBottom)
        // 创建根画布
        const rootCanvas = Canvas.newObject()
        rootCanvas.size = new Vector2(1920, 1080);
        rootCanvas.position = Vector2.zero
        rootCanvas.constraints = new UIConstraintAnchors(UIConstraintHorizontal.LeftRight, UIConstraintVertical.TopBottom)
        // 设置根画布
        this.uiWidget.rootContent = rootCanvas
        // 创建背景图
        const bg1 = Image.newObject()
        rootCanvas.addChild(bg1)
        bg1.size = new Vector2(1920, 1080)
        bg1.position = new Vector2(0, 0)
        bg1.imageGuid = "114028"
        bg1.imageColor = LinearColor.colorHexToLinearColor("000000CC")
        bg1.constraints = new UIConstraintAnchors(UIConstraintHorizontal.LeftRight, UIConstraintVertical.TopBottom)
        bg1.visibility = SlateVisibility.Visible
        // 提示内容背景图
        const bg2 = Image.newObject()
        rootCanvas.addChild(bg2)
        bg2.size = new Vector2(800, 500)
        bg2.position = new Vector2(560, 290)
        bg2.imageGuid = "114028"
        bg2.imageColor = LinearColor.colorHexToLinearColor("000000CC")
        bg2.constraints = new UIConstraintAnchors(UIConstraintHorizontal.Center, UIConstraintVertical.Center)
        // 标题
        this.titleText = TextBlock.newObject()
        bg2.addChild(this.titleText)
        this.titleText.size = new Vector2(200, 100)
        this.titleText.position = new Vector2(300, 0)
        this.titleText.autoAdjust = false
        this.titleText.fontSize = 50
        // 提示内容
        this.contentText = TextBlock.newObject()
        bg2.addChild(this.contentText)
        this.contentText.size = new Vector2(800, 300)
        this.contentText.position = new Vector2(0, 200)
        this.contentText.autoAdjust = false
        this.contentText.fontSize = 30
        this.contentText.textVerticalAlign = TextVerticalJustify.Top
    }
    public setContent(title: string, content: string) {
        this.titleText.text = title
        this.contentText.text = content
    }
    public show() {
        this.uiWidget.visibility = SlateVisibility.Visible
    }
    public hide() {
        this.uiWidget.visibility = SlateVisibility.Collapsed
    }
}