//
//  LNRoomSeatSpeakingView.swift
//  Gami
//
//  Created by OneeChan on 2026/3/17.
//

import Foundation
import UIKit
import SnapKit


class LNRoomSeatSpeakingView: UIView {
    private let borderColor: UIColor = .fill
    private let borderWidth: CGFloat = 1
    private let fillColor: UIColor = .fill.withAlphaComponent(0.5)
    private let duration: Double = 2
    private let offset = 10.0
    private let waveCount = 2
    private var borderLayers: [CAShapeLayer] = []
    
    private weak var roomSession: LNRoomSession?
    private var curIndex: Int = -1
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        clipsToBounds = false
        isUserInteractionEnabled = false
        
        for _ in 0..<waveCount {
            let borderLayer = CAShapeLayer()
            borderLayer.borderColor = borderColor.cgColor
            borderLayer.borderWidth = borderWidth
            borderLayer.backgroundColor = fillColor.cgColor
            layer.addSublayer(borderLayer)
            borderLayers.append(borderLayer)
        }
        
        LNEventDeliver.addObserver(self)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func update(_ index: Int, room: LNRoomSession?) {
        roomSession = room
        curIndex = index
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        if borderLayers.first?.bounds.height != bounds.height {
            for (index, layer) in borderLayers.enumerated() {
                layer.frame = bounds
                layer.cornerRadius = bounds.height * 0.5
                layer.removeAllAnimations()
                startAnimate(layer: layer, index: index)
            }
        }
    }
}

extension LNRoomSeatSpeakingView: LNRoomViewModelNotify {
    func onRoomSeatsChanged(session: LNRoomSession, changed: [LNRoomSeatItem]) {
        guard roomSession == session else { return }
        check()
    }
    
    func onRoomSpeakingUsersChanged(session: LNRoomSession, speakings: [String]) {
        guard roomSession == session else { return }
        check()
    }
    
    private func check() {
        guard curIndex != -1,
              let seat = roomSession?.seatsInfo.first(where: { $0.index == curIndex }) else {
            dismiss()
            return
        }
        
        if roomSession?.speakingUser.contains(seat.uid) == true {
            show()
        } else {
            dismiss()
        }
    }
}
 
extension LNRoomSeatSpeakingView {
    private func startAnimate(layer: CAShapeLayer, index: Int) {
        let scaleAnim = CABasicAnimation(keyPath: "transform.scale")
        scaleAnim.fromValue = 1.0
        scaleAnim.toValue = 1.0 + offset / CGFloat(layer.bounds.width / 2)
        scaleAnim.duration = duration
        
        let opacityAnim = CABasicAnimation(keyPath: "opacity")
        opacityAnim.fromValue = 1.0
        opacityAnim.toValue = 0.0
        opacityAnim.duration = duration
        
        let animGroup = CAAnimationGroup()
        animGroup.animations = [scaleAnim, opacityAnim]
        animGroup.duration = duration
        animGroup.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        animGroup.isRemovedOnCompletion = false
        animGroup.fillMode = .forwards
        animGroup.repeatCount = .infinity
        animGroup.beginTime = CACurrentMediaTime() + Double(index) * duration * 0.5
        layer.add(animGroup, forKey: "scaleAndFadeGroup")
    }
    
    private func show() {
        UIView.animate(withDuration: 0.25) {
            self.alpha = 1.0
        }
    }
    
    private func dismiss() {
        UIView.animate(withDuration: 0.25) {
            self.alpha = 0.0
        }
    }
}

#if DEBUG

import SwiftUI

struct LNRoomSeatSpeakingViewPreview: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        let container = UIView()
        container.backgroundColor = .lightGray
        
        let view = LNRoomSeatSpeakingView()
        container.addSubview(view)
        view.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.width.height.equalTo(50)
        }
        
        return container
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) { }
}

#Preview(body: {
    LNRoomSeatSpeakingViewPreview()
})
#endif
