/* While this template provides a good starting point for using Wear Compose, you can always
 * take a look at https://github.com/android/wear-os-samples/tree/main/ComposeStarter to find the
 * most up to date changes to the libraries and their usages.
 */

package com.epfl.esl.sportstracker.presentation

import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Build
import android.os.Bundle
import android.os.PowerManager
import android.util.Log
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.tooling.preview.devices.WearDevices
import com.epfl.esl.sportstracker.R
import com.epfl.esl.sportstracker.presentation.theme.SportsTrackerTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import com.google.android.gms.wearable.DataClient
import com.google.android.gms.wearable.DataEvent
import com.google.android.gms.wearable.DataEventBuffer
import com.google.android.gms.wearable.DataMapItem
import com.google.android.gms.wearable.Wearable
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.res.imageResource
import com.google.android.gms.wearable.MessageClient
import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.PutDataMapRequest
import com.google.android.gms.wearable.PutDataRequest
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.Timer
import kotlin.concurrent.timerTask

class MainActivity : ComponentActivity(), DataClient.OnDataChangedListener,
    SensorEventListener,
    MessageClient.OnMessageReceivedListener {

    private var bitmap by mutableStateOf<Bitmap?>(null)
    private var username by mutableStateOf("Hello World!")

    lateinit var mSensorManager : SensorManager
    lateinit var mHeartRateSensor : Sensor

    private var heartRate by mutableStateOf<Int>(0)

    private var timer = Timer()

    lateinit var databaseRoom: HRDao


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mSensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
        mHeartRateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE)!!

        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        val application = requireNotNull(this).application
        val dataSource = HRDatabase.getInstance(application).heartRateDao
        databaseRoom = dataSource

        setContent {
            SportsTrackerTheme {
                HomeScreen(username, bitmap, heartRate)
            }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && checkSelfPermission("android.permission.BODY_SENSORS")
            == PackageManager.PERMISSION_DENIED) {
            requestPermissions(arrayOf("android.permission.BODY_SENSORS"), 0)
        }
    }

    override fun onResume() {
        super.onResume()
        Wearable.getDataClient(this).addListener(this)
        mSensorManager.registerListener(this, mHeartRateSensor,
            SensorManager.SENSOR_DELAY_UI)
        Wearable.getMessageClient(this).addListener(this)
    }
    override fun onPause() {
        super.onPause()
        Wearable.getDataClient(this).removeListener(this)
        mSensorManager.unregisterListener(this)
        Wearable.getMessageClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.filter { it.type == DataEvent.TYPE_CHANGED &&
                it.dataItem.uri.path == "/userInfo" }
            .forEach { event ->
                val receivedImageBytes: ByteArray? =
                    DataMapItem.fromDataItem(event.dataItem).dataMap.
                    getByteArray("profileImage")

                receivedImageBytes?.let {
                    bitmap = BitmapFactory.decodeByteArray(
                        receivedImageBytes, 0,
                        receivedImageBytes.size)
                }

                username  = DataMapItem.fromDataItem(event.dataItem)
                    .dataMap.getString("username") ?: ""
            }
    }

    override fun onSensorChanged(p0: SensorEvent?) {
        heartRate = p0?.values?.get(0)?.toInt() ?: 0
    }

    override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
        //TODO("Not yet implemented")
    }

    private fun sendDataToMobile(heartRateList: ArrayList<Int>) {
        val dataClient: DataClient = Wearable.getDataClient(this)
        val putDataReq: PutDataRequest = PutDataMapRequest.create("/heart_rate")
            .run {
                dataMap.putIntegerArrayList("HEART_RATE", heartRateList)
                asPutDataRequest()
            }
        dataClient.putDataItem(putDataReq)
    }

    override fun onMessageReceived(p0: MessageEvent) {
        if(p0.path == "/command") {
            val receivedCommand: String = String(p0.data)
            if (receivedCommand == "Start") {
                timer = Timer()
                timer.schedule(timerTask {
                    insertHRToRoom(heartRate)
                }, 0, 500)
            } else if (receivedCommand == "Stop") {
                timer.cancel()
            }
        }
    }

    /** wear -> MainActivity.kt -> insertHRToRoom(...) **/
    private fun insertHRToRoom(heartRate: Int) {
        var asyncHRToSend : List<HREntity>? = null
        GlobalScope.launch {
            val valHR = HREntity (HRValue = heartRate)
            databaseRoom.insert(valHR)
            if (databaseRoom.size() >= 5) {
                asyncHRToSend = databaseRoom.getAllHRValues()
                Log.i("MainActivity", "database size $asyncHRToSend")
                val HRListToSend = ArrayList(asyncHRToSend!!.map { hrEntity ->
                    hrEntity.HRValue })
                sendDataToMobile(HRListToSend)
                databaseRoom.clear()
            }
        }
    }
}

@Composable
fun HomeScreen(username: String, bitmap: Bitmap?, heartRate: Int,
               modifier: Modifier = Modifier) {
    ConstraintLayout( modifier = Modifier.fillMaxSize().background(color = Color.Black)) {
        val (image, text, sensor) = createRefs()

        val context = LocalContext.current
        val displayBitmap = bitmap?.asImageBitmap()
            ?: ImageBitmap.Companion.imageResource(
                context.resources, R.drawable.ic_logo)

        Image(
            bitmap = displayBitmap,
            contentDescription = "Logo Sports Tracker",
            modifier = modifier
                .size(100.dp)
                .constrainAs(image) {
                    centerHorizontallyTo(parent)
                    top.linkTo(parent.top)
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    bottom.linkTo(text.top)
                }
        )

        Text(
            text = username,
            style = TextStyle(fontSize = 24.sp),
            modifier = modifier
                .constrainAs(text) {
                    centerHorizontallyTo(parent)
                    top.linkTo(image.bottom)
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    bottom.linkTo(parent.bottom)
                }
        )

        Text(text = "HR = $heartRate",
            modifier = modifier
                .constrainAs(sensor) {
                    top.linkTo(text.bottom)
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    bottom.linkTo(parent.bottom)
                }
                .padding(start = 16.dp, end = 16.dp)
        )
    }

}



@Preview(device = WearDevices.LARGE_ROUND, showSystemUi = true)

@Composable
fun HomeScreenPreview() {
    HomeScreen("Test", null, 0)
}