//
//  ViewController.swift
//  SPMDemo
//

import AVFoundation
import UIKit

import PRESTOplay
import CastlabsApple
import CastlabsVT

class ViewController: UIViewController {
    private struct StreamItem {
        let title: String
        let url: String
    }

    private let streams: [StreamItem] = [
        StreamItem(title: "HLS", url: "https://demo.cf.castlabs.com/media/prestohls/master.m3u8"),
        StreamItem(title: "DASH Tears of Steel", url: "https://demo.cf.castlabs.com/media/TOS/abr/Manifest_clean_sizes.mpd")
    ]

    private var player = PRESTOplaySDK.shared.player()

    private let homeView = UIView()
    private let playbackView = UIView()
    private let tableView = UITableView(frame: .zero, style: .insetGrouped)
    private let playerContainerView = UIView()
    private let controlsStack = UIStackView()
    private let playPauseButton = UIButton(type: .system)
    private let seekSlider = UISlider()
    private let timeLabel = UILabel()
    private let backButton = UIButton(type: .system)

    private var duration: Double = 0
    private var isSeeking = false

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "SPM Integration"
        view.backgroundColor = .systemBackground

        setupHomeView()
        setupPlaybackView()
        showHome()

        player.onState = { [weak self] _, _ in
            guard let self else { return }
            if let error = self.player.error {
                print("Error \(error)")
            }
            self.updatePlayPauseButton()
        }

        player.onCurrentTime(rate: 0.2) { [weak self] position in
            guard let self else { return }
            guard self.isSeeking == false else { return }

            let duration = self.player.duration
            self.duration = duration
            if duration > 0 {
                self.seekSlider.value = Float((position / duration) * 100.0)
            } else {
                self.seekSlider.value = 0
            }
            self.timeLabel.text = "\(self.formatTime(position)) / \(self.formatTime(duration))"
        }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        player.update(size: playerContainerView.bounds.size)
    }

    private func setupHomeView() {
        homeView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(homeView)

        NSLayoutConstraint.activate([
            homeView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            homeView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            homeView.topAnchor.constraint(equalTo: view.topAnchor),
            homeView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])

        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "StreamCell")
        homeView.addSubview(tableView)

        NSLayoutConstraint.activate([
            tableView.leadingAnchor.constraint(equalTo: homeView.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: homeView.trailingAnchor),
            tableView.topAnchor.constraint(equalTo: homeView.safeAreaLayoutGuide.topAnchor),
            tableView.bottomAnchor.constraint(equalTo: homeView.bottomAnchor)
        ])
    }

    private func setupPlaybackView() {
        playbackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(playbackView)

        NSLayoutConstraint.activate([
            playbackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            playbackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            playbackView.topAnchor.constraint(equalTo: view.topAnchor),
            playbackView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])

        backButton.translatesAutoresizingMaskIntoConstraints = false
        backButton.setTitle("Back", for: .normal)
        backButton.addTarget(self, action: #selector(backTapped), for: .touchUpInside)
        playbackView.addSubview(backButton)

        playerContainerView.translatesAutoresizingMaskIntoConstraints = false
        playerContainerView.backgroundColor = .black
        playbackView.addSubview(playerContainerView)

        controlsStack.translatesAutoresizingMaskIntoConstraints = false
        controlsStack.axis = .vertical
        controlsStack.spacing = 12
        playbackView.addSubview(controlsStack)

        playPauseButton.setTitle("Pause", for: .normal)
        playPauseButton.addTarget(self, action: #selector(playPauseTapped), for: .touchUpInside)

        seekSlider.minimumValue = 0
        seekSlider.maximumValue = 100
        seekSlider.addTarget(self, action: #selector(seekTouchDown), for: .touchDown)
        seekSlider.addTarget(self, action: #selector(seekChanged), for: .valueChanged)
        seekSlider.addTarget(self, action: #selector(seekTouchUp), for: [.touchUpInside, .touchUpOutside, .touchCancel])

        timeLabel.text = "00:00 / 00:00"
        timeLabel.textAlignment = .center
        timeLabel.font = .monospacedDigitSystemFont(ofSize: 14, weight: .regular)

        controlsStack.addArrangedSubview(playPauseButton)
        controlsStack.addArrangedSubview(seekSlider)
        controlsStack.addArrangedSubview(timeLabel)

        NSLayoutConstraint.activate([
            backButton.leadingAnchor.constraint(equalTo: playbackView.safeAreaLayoutGuide.leadingAnchor, constant: 16),
            backButton.topAnchor.constraint(equalTo: playbackView.safeAreaLayoutGuide.topAnchor, constant: 8),

            playerContainerView.leadingAnchor.constraint(equalTo: playbackView.leadingAnchor),
            playerContainerView.trailingAnchor.constraint(equalTo: playbackView.trailingAnchor),
            playerContainerView.topAnchor.constraint(equalTo: backButton.bottomAnchor, constant: 12),
            playerContainerView.heightAnchor.constraint(equalTo: playbackView.heightAnchor, multiplier: 0.5),

            controlsStack.leadingAnchor.constraint(equalTo: playbackView.leadingAnchor, constant: 16),
            controlsStack.trailingAnchor.constraint(equalTo: playbackView.trailingAnchor, constant: -16),
            controlsStack.topAnchor.constraint(equalTo: playerContainerView.bottomAnchor, constant: 16)
        ])
    }

    private func showHome() {
        homeView.isHidden = false
        playbackView.isHidden = true
    }

    private func showPlayback() {
        homeView.isHidden = true
        playbackView.isHidden = false
    }

    private func startPlayback(stream: StreamItem) {
        guard let contentURL = URL(string: stream.url) else { return }

        title = stream.title
        let config = PlayerConfiguration(with: contentURL)
        player.load(config: config)
        player.attach(to: playerContainerView.layer)
        player.open(autoplay: true)
        updatePlayPauseButton()
        showPlayback()
    }

    @objc private func backTapped() {
        player.stop()
        seekSlider.value = 0
        timeLabel.text = "00:00 / 00:00"
        duration = 0
        title = "SPM Integration"
        showHome()
    }

    @objc private func playPauseTapped() {
        if player.playbackState == .playing {
            player.pause()
        } else {
            player.play()
        }
        updatePlayPauseButton()
    }

    @objc private func seekTouchDown() {
        isSeeking = true
    }

    @objc private func seekChanged() {
        guard duration > 0 else { return }
        let position = (Double(seekSlider.value) / 100.0) * duration
        timeLabel.text = "\(formatTime(position)) / \(formatTime(duration))"
    }

    @objc private func seekTouchUp() {
        guard duration > 0 else {
            isSeeking = false
            return
        }

        let position = (Double(seekSlider.value) / 100.0) * duration
        let time = CMTime(seconds: position, preferredTimescale: 1000)
        player.seek(time)
        isSeeking = false
    }

    private func updatePlayPauseButton() {
        let title = player.playbackState == .playing ? "Pause" : "Play"
        playPauseButton.setTitle(title, for: .normal)
    }

    private func formatTime(_ seconds: Double) -> String {
        guard seconds.isFinite, seconds >= 0 else { return "00:00" }
        let total = Int(seconds.rounded(.down))
        let mins = total / 60
        let secs = total % 60
        return String(format: "%02d:%02d", mins, secs)
    }
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        streams.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "StreamCell", for: indexPath)
        var config = cell.defaultContentConfiguration()
        config.text = streams[indexPath.row].title
        config.secondaryText = streams[indexPath.row].url
        config.secondaryTextProperties.numberOfLines = 1
        cell.contentConfiguration = config
        cell.accessoryType = .disclosureIndicator
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        startPlayback(stream: streams[indexPath.row])
    }
}
