package com.github.premnirmal.ticker

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.DialogInterface.OnClickListener
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import com.github.premnirmal.ticker.components.AppClock.AppClockImpl
import com.github.premnirmal.tickerwidget.R
import java.text.NumberFormat
import java.text.SimpleDateFormat
import java.time.DayOfWeek
import java.time.ZonedDateTime
import java.time.format.TextStyle.SHORT
import java.util.Date
import java.util.Locale

@RequiresApi(33)
fun Context.hasNotificationPermission(): Boolean {
    return checkCallingOrSelfPermission(
        Manifest.permission.POST_NOTIFICATIONS
    ) == PackageManager.PERMISSION_GRANTED
}

fun Activity.showDialog(
    message: String,
    cancelable: Boolean = true
): AlertDialog {
    return AlertDialog.Builder(this).setMessage(message).setCancelable(cancelable)
        .setNeutralButton(R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() }.show()
}

fun Context.showDialog(
    title: String,
    message: String,
    cancelable: Boolean = true,
    listener: OnClickListener
) {
    AlertDialog.Builder(
        this
    ).setTitle(title).setMessage(message).setCancelable(cancelable).setNeutralButton(R.string.ok, listener).show()
}

fun Context.showDialog(
    title: String,
    message: String,
    positiveButton: String,
    negativeButton: String,
    cancelable: Boolean = true,
    listener: OnClickListener
) {
    AlertDialog.Builder(
        this
    ).setTitle(title).setMessage(message).setCancelable(cancelable).setPositiveButton(positiveButton, listener)
        .setNegativeButton(negativeButton, listener).show()
}

fun Context.showDialog(message: String): AlertDialog {
    return AlertDialog.Builder(this).setMessage(message).setCancelable(false)
        .setNeutralButton(R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() }.show()
}

fun Context.showDialog(@StringRes stringRes: Int): AlertDialog {
    return AlertDialog.Builder(this).setMessage(stringRes).setCancelable(false)
        .setNeutralButton(R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() }.show()
}

fun Context.isNetworkOnline(): Boolean {
    val connectivityManager =
        getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager ?: return false
    val network = connectivityManager.activeNetwork ?: return false
    val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
    return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
        capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}

fun ZonedDateTime.createTimeString(): String {
    val fetched: String
    val fetchedDayOfWeek = dayOfWeek.value
    val today = AppClockImpl.todayZoned().dayOfWeek.value
    fetched = if (today == fetchedDayOfWeek) {
        AppPreferences.TIME_FORMATTER.format(this)
    } else {
        val day: String = DayOfWeek.from(this).getDisplayName(SHORT, Locale.getDefault())
        val timeStr: String = AppPreferences.TIME_FORMATTER.format(this)
        "$timeStr $day"
    }
    return fetched
}

fun Float.format(fractionDigits: Int = 2): String {
    return NumberFormat.getInstance(Locale.getDefault()).run {
        minimumFractionDigits = fractionDigits
        maximumFractionDigits = fractionDigits
        format(this@format)
    }
}

fun Long.format(): String {
    return NumberFormat.getInstance(Locale.getDefault()).format(this)
}

fun Long.formatDate(format: String): String {
    return SimpleDateFormat(format, Locale.getDefault()).format(Date(this))
}

fun Long.formatBigNumbers(context: Context): String {
    return when {
        this < 100_000 -> NumberFormat.getInstance(Locale.getDefault()).format(this)
        this < 1_000_000 -> context.getString(R.string.number_format_thousands, this.div(1000.0))
        this < 1_000_000_000 -> {
            context.getString(R.string.number_format_millions, this.div(1000000.0))
        }

        this < 1_000_000_000_000 -> {
            context.getString(R.string.number_format_billions, this.div(1000000000.0))
        }

        else -> {
            context.getString(R.string.number_format_trillions, this.div(1000000000000.0))
        }
    }
}
