package com.omixlab.mosis

import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.content.res.AssetManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.MotionEvent
import android.view.Surface
import android.view.SurfaceView
import android.view.SurfaceHolder
import androidx.activity.ComponentActivity
import androidx.activity.enableEdgeToEdge
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.viewinterop.AndroidView

class MainActivity : ComponentActivity() {
    init {
        System.loadLibrary("mosis-test")
    }

    companion object {
        // Singleton for test access
        @Volatile
        var instance: MainActivity? = null
            private set

        // Intent actions for event injection via broadcast
        const val ACTION_INJECT_TOUCH = "com.omixlab.mosis.INJECT_TOUCH"
        const val EXTRA_TOUCH_TYPE = "touch_type"  // "down", "move", "up", "click"
        const val EXTRA_X = "x"  // Normalized 0.0-1.0
        const val EXTRA_Y = "y"  // Normalized 0.0-1.0
    }

    var remote_service: IMosisService? = null
    var statusText = mutableStateOf("Status: idle")
    var buttonText = mutableStateOf("Init OS")
    val connection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, service: IBinder) {
            Log.d("MosisTest", "Service Connected")
            statusText.value = "Service Connected"
            remote_service = IMosisService.Stub.asInterface(service)
            serviceConnected(service)
            initOS()
        }

        override fun onServiceDisconnected(arg0: ComponentName) {
            Log.d("MosisTest", "Service Disconnected")
            statusText.value = "Service Disconnected"
        }
    }
    val viewport = object : SurfaceHolder.Callback {
        override fun surfaceCreated(holder: SurfaceHolder) {
            Log.d("MosisTest", "surfaceCreated")
            setSurface(holder.surface)
        }
        override fun surfaceChanged(
            holder: SurfaceHolder,
            format: Int,
            width: Int,
            height: Int
        ) {
            // Optional: Pass resize events to native if needed
            // resizeSurface(width, height)
            Log.d("MosisTest", "surfaceResized")

        }
        override fun surfaceDestroyed(holder: SurfaceHolder) {
            destroySurface()
            Log.d("MosisTest", "surfaceDestroyed")
        }
    }
    fun startRemoteService() {
        val intent = Intent("com.omixlab.mosis.SERVICE")
        intent.setPackage("com.omixlab.mosis")
        try {
            startForegroundService(intent)
            val result = bindService(intent, connection, BIND_AUTO_CREATE)
            Log.d("ServiceTester", "Bind result: $result")
        } catch (e: Exception) {
            Log.e("ServiceTester", "Bind failed", e)
        }
    }
    // Broadcast receiver for event injection (for testing)
    private val touchInjectionReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == ACTION_INJECT_TOUCH) {
                val touchType = intent.getStringExtra(EXTRA_TOUCH_TYPE) ?: return
                val x = intent.getFloatExtra(EXTRA_X, 0.5f)
                val y = intent.getFloatExtra(EXTRA_Y, 0.5f)
                Log.d("MosisTest", "Injecting touch: $touchType at ($x, $y)")
                when (touchType) {
                    "down" -> injectTouchDown(x, y)
                    "move" -> injectTouchMove(x, y)
                    "up" -> injectTouchUp(x, y)
                    "click" -> injectClick(x, y)
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        instance = this
        setAssetManager(assets)
        startRemoteService()
        enableEdgeToEdge()

        // Register broadcast receiver for touch injection (testing)
        val filter = IntentFilter(ACTION_INJECT_TOUCH)
        registerReceiver(touchInjectionReceiver, filter, RECEIVER_EXPORTED)

        setContent {
            Column(
                modifier = Modifier.fillMaxSize(),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
                Text("Welcome to Mosis OS")
                Button(onClick = { initOS() }) {
                    Text(buttonText.value)
                }
                Text(statusText.value)
                NativeViewport(
                    modifier = Modifier
                        .fillMaxSize(0.8f)
                )
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        instance = null
        try {
            unregisterReceiver(touchInjectionReceiver)
        } catch (e: Exception) {
            Log.w("MosisTest", "Receiver not registered", e)
        }
    }

    /**
     * Inject a touch down event at normalized coordinates (0.0-1.0)
     */
    fun injectTouchDown(x: Float, y: Float) {
        Log.d("MosisTest", "Inject touch down: ($x, $y)")
        remote_service?.onTouchDown(x, y)
    }

    /**
     * Inject a touch move event at normalized coordinates (0.0-1.0)
     */
    fun injectTouchMove(x: Float, y: Float) {
        Log.d("MosisTest", "Inject touch move: ($x, $y)")
        remote_service?.onTouchMove(x, y)
    }

    /**
     * Inject a touch up event at normalized coordinates (0.0-1.0)
     */
    fun injectTouchUp(x: Float, y: Float) {
        Log.d("MosisTest", "Inject touch up: ($x, $y)")
        remote_service?.onTouchUp(x, y)
    }

    /**
     * Inject a complete click (down + up) at normalized coordinates
     */
    fun injectClick(x: Float, y: Float, delayMs: Long = 50) {
        Log.d("MosisTest", "Inject click: ($x, $y)")
        remote_service?.onTouchDown(x, y)
        android.os.Handler(mainLooper).postDelayed({
            remote_service?.onTouchUp(x, y)
        }, delayMs)
    }
    @SuppressLint("ClickableViewAccessibility")
    @Composable
    fun NativeViewport(modifier: Modifier = Modifier) {
        AndroidView(
            modifier = modifier,
            factory = { context ->
                SurfaceView(context).apply {
                    holder.addCallback(viewport)
                    setOnTouchListener { v, event ->
                        when (event.action) {
                            MotionEvent.ACTION_DOWN -> {
                                Log.d("ServiceTester", "ACTION_DOWN ${event.x} - ${event.y}")
                                remote_service?.onTouchDown(event.x /v.width, event.y / v.height)
                                true
                            }
                            MotionEvent.ACTION_MOVE -> {
                                Log.d("ServiceTester", "ACTION_MOVE ${event.x} - ${event.y}")
                                remote_service?.onTouchMove(event.x /v.width, event.y / v.height)
                                true
                            }
                            MotionEvent.ACTION_UP -> {
                                Log.d("ServiceTester", "ACTION_ ${event.x} - ${event.y}")
                                remote_service?.onTouchUp(event.x /v.width, event.y / v.height)
                                true
                            }
                            else -> false
                        }
                    }
                }
            }
        )
    }
    external fun setAssetManager(assetManager: AssetManager)
    external fun serviceConnected(binder: IBinder)
    external fun setSurface(surface: Surface)
    external fun destroySurface()
    external fun initOS()
}