package app.guru.guru_platform_data

import android.app.Activity
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.view.WindowManager;
import android.util.Log
import androidx.annotation.NonNull
import guru.core.checker.GuruChecker
import io.flutter.embedding.engine.FlutterJNI
import java.time.ZoneId
import java.util.*

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import android.content.SharedPreferences
import androidx.preference.PreferenceManager

/** GuruPlatformDataPlugin */
class GuruPlatformData : FlutterPlugin, MethodCallHandler, ActivityAware {
    private var activity: Activity? = null

    companion object {
        object MethodNames {
            const val GetAdsLimitTracking = "get_ads_limit_tracking"
            const val ShowMediationDebugger = "show_mediation_debugger"
            const val GetObservatoryUri = "get_observatory_uri"
            const val IsCutoutScreen = "is_cutout_screen"
            const val IsAppInstalled = "is_app_installed"
            const val GetBrightness = "get_brightness"
            const val SetBrightness = "set_brightness"
            const val ResetBrightness = "reset_brightness"
            const val IsKeptScreenOn = "is_kept_screen_on"
            const val KeepScreenOn = "keep_screen_on"
            const val GetLocalTimezone = "getLocalTimezone"
            const val GetAvailableTimezones = "getAvailableTimezones"
            const val GetPurposeConsents = "get_purpose_consents"
        }
    }

    /// The MethodChannel that will the communication between Flutter and native Android
    ///
    /// This local reference serves to register the plugin with the Flutter Engine and unregister it
    /// when the Flutter Engine is detached from the Activity
    private lateinit var channel: MethodChannel

    private val handler = Handler(Looper.getMainLooper())

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "app.guru.guru_platform_data")
        channel.setMethodCallHandler(this)
    }

    private fun dispatch(call: MethodCall, result: MethodChannel.Result) {
        when (call.method) {
            MethodNames.GetObservatoryUri -> {
                handler.post {
                    result.success(FlutterJNI.getObservatoryUri())
                }
            }

            MethodNames.IsCutoutScreen -> {
                handler.post {
                    val cutoutScreen = isCutoutScreen()
                    Log.d("PDC", "cutoutScreen:$cutoutScreen")
                    result.success(isCutoutScreen())
                }
            }

            MethodNames.IsAppInstalled -> {
                handler.post {
                    val pkg = call.argument<String>("package_name") ?: ""
                    Log.d("PDC", "isAppInstalled:$pkg")
                    result.success(GuruChecker.isAppInstalled(activity!!, pkg))
                }
            }

            MethodNames.GetBrightness -> {
                handler.post {
                    val brightness = getBrightness()
                    Log.d("PDC", "GetBrightness:$brightness")
                    result.success(brightness)
                }
            }

            MethodNames.SetBrightness -> {
                handler.post {
                    val brightness = call.argument<Double>("brightness") ?: 1.0
                    Log.d("PDC", "brightness:$brightness")
                    setBrightness(brightness.toFloat())
                    result.success(true)
                }
            }

            MethodNames.IsKeptScreenOn -> {
                handler.post {
                    val flags = activity?.window?.attributes?.flags ?: 0;
                    Log.d("PDC", "IsKeptScreenOn flags:$flags")
                    result.success((flags and WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0)
                }
            }

            MethodNames.KeepScreenOn -> {
                handler.post {
                    val on: kotlin.Boolean? = call.argument("on")
                    Log.d("PDC", "KeepScreenOn on:$on")
                    val success = if (on == null) {
                        false
                    } else if (on) {
                        activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
                        true
                    } else {
                        activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
                        true
                    }
                    result.success(success)
                }
            }

            MethodNames.ResetBrightness -> {
                handler.post {
                    val lp = activity?.window?.attributes?.apply {
                        screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
                    }
                    activity?.window?.attributes = lp
                    result.success(true)
                }
            }

            MethodNames.GetLocalTimezone -> {
                handler.post {
                    result.success(getLocalTimezone())
                }
            }

            MethodNames.GetAvailableTimezones -> {
                handler.post {
                    result.success(getAvailableTimezones())
                }
            }

            MethodNames.GetPurposeConsents -> {
                handler.post {
                    val purposeConsents = activity?.let {
                        val sharedPref: SharedPreferences =
                            PreferenceManager.getDefaultSharedPreferences(it)
                        // Example value: "1111111111"
                        return@let sharedPref.getString("IABTCF_PurposeConsents", "")
                    } ?: ""

                    result.success(purposeConsents)
                    // Purposes are zero-indexed. Index 0 contains information about Purpose 1.
                    // if (!purposeConsents.isEmpty()) {
                    //     val purposeOneString: String = purposeConsents.charAt(0)
                    //     val hasConsentForPurposeOne = purposeOneString.equals("1")
                    // }
                }
            }

            else -> {
                handler.post {
                    result.error("not impl!!!", "${call.method} not impl!", "")
                }
            }
        }

    }

    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
        dispatch(call, result);
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }


    private fun isCutoutScreen(): Boolean = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        activity?.let {
            it.window.decorView.rootWindowInsets.displayCutout != null
        } ?: false
    } else {
        false
    }

    private fun getBrightness(): Float {
        var result: Float = activity?.window?.attributes?.screenBrightness ?: 1.0f
        if (result < 0) { // the application is using the system brightness
            try {
                result = Settings.System.getInt(
                    activity?.contentResolver,
                    Settings.System.SCREEN_BRIGHTNESS
                ) / 255f
            } catch (e: Settings.SettingNotFoundException) {
                result = 1.0f
                e.printStackTrace()
            }
        }
        return result
    }

    private fun getLocalTimezone(): String {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ZoneId.systemDefault().id
        } else {
            TimeZone.getDefault().id
        }
    }

    private fun getAvailableTimezones(): List<String> {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ZoneId.getAvailableZoneIds().toCollection(ArrayList())
        } else {
            TimeZone.getAvailableIDs().toCollection(ArrayList())
        }
    }

    private fun setBrightness(brightness: Float) {
        val lp = activity?.window?.attributes?.apply {
            screenBrightness = brightness
        }
        activity?.window?.attributes = lp
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    }

    override fun onDetachedFromActivity() {
        activity = null
    }
}
