//
//  SDLViewController.swift
//  Ryujinx
//
//  Created by Stossy11 on 3/10/2024.
//

import SwiftUI
import UIKit
import SDL
import LibRyujinx


class SDLViewController: UIViewController {
    var game: Game?

    init(game: Game) {
        self.game = game
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Initialize SDL for iOS rendering
        // Set up SDL window and renderer
        let windowFlags: UInt32 = SDL_WINDOW_SHOWN.rawValue | SDL_WINDOW_ALLOW_HIGHDPI.rawValue
        
        #if !targetEnvironment(simulator)
        let window = SDL_CreateWindow("Ryujinx Emulator",
                                      Int32(self.view.frame.origin.x),
                                      Int32(self.view.frame.origin.y),
                                      Int32(self.view.frame.size.width),
                                      Int32(self.view.frame.size.height),
                                      windowFlags)
        
        let renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED.rawValue)
        SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear")
        SDL_RenderSetLogicalSize(renderer, Int32(self.view.frame.size.width), Int32(self.view.frame.size.height))

        // Load and run the game
        loadGameAndRun(renderer)
        #endif
    }
    
    func loadGameAndRun(_ renderer: OpaquePointer?) {
        guard let game = game else { return }

        // Prepare the emulator with the selected game
        #if !targetEnvironment(simulator)
        // Load the game file into the emulator
        let gamePath = game.fileURL.path(percentEncoded: false)
        
        do {
            let gotAccess = game.fileURL.startAccessingSecurityScopedResource()

            // Initialize the device/emulation
            let handle = try FileHandle(forReadingFrom: game.fileURL)
            
            #if !targetEnvironment(simulator)
            let fileDescriptor = handle.fileDescriptor
            let cpuRecompilation = true // Enable JIT recompilation
            let hardwareAcceleration = true // Enable hardware acceleration (GPU)
            let cpuCores = 4 // Set to 4 CPU cores
            let memorySize = 4 * 1024 // 4GB memory
            let macroHLE = true // Enable macro high-level emulation
            let fastEmulation = true // Fast GPU or CPU emulation
            let shaderCaching = true // Enable shader/texture caching
            let useVulkan = true // Use Vulkan as backend
            let systemContext: Int64 = 0 // Handle for system or graphics context (could be nil or 0)
            let enableVSync = true // Enable vertical synchronization

            let isInitialized = device_initialize(cpuRecompilation, hardwareAcceleration, Int32(cpuCores), Int32(memorySize), macroHLE, fastEmulation, shaderCaching, useVulkan, Int(systemContext), enableVSync)

            if isInitialized {
                let isLoaded = device_load(Int(fileDescriptor))
                if isLoaded {
                    print("Game \(game.titleName) loaded successfully!")
                    
                    var isRunning = true
                    
                    while isRunning {
                        // Process SDL events like touch, button presses, etc.
                        var event = SDL_Event()
                        while SDL_PollEvent(&event) != 0 {
                            if event.type == SDL_QUIT.rawValue {
                                isRunning = false
                            }
                        }

                        // Clear screen
                        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255)
                        SDL_RenderClear(renderer)

                        // Run the emulation frame
                        graphics_renderer_run_loop()

                        // Present the rendered frame
                        SDL_RenderPresent(renderer)
                    }
                } else {
                    print("Failed to load the game \(game.titleName).")
                }
            } else {
                print("Failed to initialize the device for \(game.titleName).")
            }
            #endif

            try handle.close()
            if gotAccess {
                print("Failed to get access to game file at \(game.fileURL.path)")
                game.fileURL.stopAccessingSecurityScopedResource()
            }
        } catch {
            print("Error starting emulation for game \(game.titleName): \(error)")
        }

        // Emulation and rendering loop

        // Clean up
        SDL_DestroyRenderer(renderer)
        SDL_Quit()
        #endif
    }
}


struct SDLView: UIViewControllerRepresentable {
    var game: Game

    func makeUIViewController(context: Context) -> SDLViewController {
        return SDLViewController(game: game) // Pass the game to the controller
    }

    func updateUIViewController(_ uiViewController: SDLViewController, context: Context) {
        // No updates necessary for this view
    }
}
