package uz.mobiuz.mobiservice.dev.utils.extensions

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Vibrator
import android.text.*
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textfield.TextInputEditText
import com.google.gson.JsonSyntaxException
import retrofit2.HttpException
import uz.mobiuz.mobiservice.dev.R
import uz.mobiuz.mobiservice.dev.network.model.Errors
import uz.mobiuz.mobiservice.dev.ui.global.CONSTANTS
import uz.mobiuz.mobiservice.dev.ui.global.ExitDialog
import uz.mobiuz.mobiservice.dev.ui.global.OfflineBottomSheet
import uz.mobiuz.mobiservice.dev.ui.global.SenderDialog
import uz.mobiuz.mobiservice.dev.utils.NetworkUtil
import java.io.IOException
import java.net.ConnectException
import java.sql.Timestamp
import java.text.SimpleDateFormat


fun Fragment.showMessage(message: String) {
    Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}

fun Fragment.showCustomDialog(description: String, status: Boolean, block: () -> Unit) {
    val dialog = SenderDialog(description, status)
    dialog.setOnClickListener {
        block()
    }
    dialog.show(childFragmentManager, "tab")
}

fun String.getDateTime(): String? {
    return try {
        val long = Timestamp.parse(this)
        val sdf = SimpleDateFormat("MM/dd/yyyy")
        sdf.format(long)
    } catch (e: Exception) {
        ""
    }
}

fun FragmentActivity.showOfflineBottomSheetDialog() {
    val fragment = supportFragmentManager.findFragmentByTag(CONSTANTS.FULL_SCREEN_DIALOG)
    if (fragment == null) OfflineBottomSheet().show(supportFragmentManager, CONSTANTS.FULL_SCREEN_DIALOG)
}

fun Activity.showMessage(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}


fun Fragment.customLog(message: Any) {
    Log.e("AAA", message.toString())
}

fun Activity.customLog(message: Any) {
    Log.e("AAA", message.toString())
}

fun RecyclerView.customLog(message: Any) {
    Log.e("AAA", message.toString())
}


fun Throwable.userMessage(context: Context) = when (this) {
    is HttpException -> when (this.code()) {
        304 -> context.getString(R.string.ex304)
        400 -> context.getString(R.string.ex400)
        401 -> {
            context.sendBroadcast(Intent(CONSTANTS.UNAUTHORIZED))
            context.getString(R.string.ex401)
        }
        403 -> context.getString(R.string.ex403)
        404 -> context.getString(R.string.ex404)
        405 -> context.getString(R.string.ex405)
        406 -> context.getString(R.string.ex406)
        408 -> context.getString(R.string.ex408)
        409 -> context.getString(R.string.ex409)
        413 -> context.getString(R.string.ex413)
        429 -> context.getString(R.string.ex429)
        500 -> context.getString(R.string.ex500)
        else -> context.getString(R.string.exelse)
    }
    is IOException -> context.getString(R.string.ioexception)
    is JsonSyntaxException -> context.getString(R.string.jsonsyntaxexception)
    is ConnectException -> context.getString(R.string.connect_exception)
    else -> context.getString(R.string.ex_nothing)
}

fun Fragment.showCustomExitDialog(block: () -> Unit) {
    val dialog = ExitDialog()
    dialog.setOnDoneListener {
        block()
    }
    dialog.show(childFragmentManager, "childFragmentManager")
}

fun FragmentActivity.showCustomExitDialog(block: () -> Unit) {
    val dialog = ExitDialog()
    dialog.setOnDoneListener {
        block()
    }
    dialog.show(supportFragmentManager, "childFragmentManager")
}

fun String.checkChangedPosition(new: String): Int {
    for (i in this.indices) {
        if (i == new.length) {
            return new.length
        } else if (this[i] != new[i]) {
            return i
        }
    }
    return new.length
}

fun View.getStatusBarHeight(): Int {
    var result = 0
    val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
    if (resourceId > 0) {
        result = resources.getDimensionPixelSize(resourceId)
    }
    resources.displayMetrics.heightPixels
    return result
}

fun String.maskedTextMobi(): String {
    var newText = ""
    for (i in this.indices) {
        if (i == 4 || i == 6 || i == 9 || i == 11) {
            newText += " "
        }
        newText += this[i]

    }

    return newText
}

fun TextView.makeLinks(vararg links: Pair<String, View.OnClickListener>) {
    val spannableString = SpannableString(this.text)
    var startIndexOfLink = -1
    for (link in links) {
        val clickableSpan = object : ClickableSpan() {
            override fun updateDrawState(textPaint: TextPaint) {
                // use this to change the link color
                textPaint.color = textPaint.linkColor
                // toggle below value to enable/disable
                // the underline shown below the clickable text
                textPaint.isUnderlineText = true
            }

            override fun onClick(view: View) {
                Selection.setSelection((view as TextView).text as Spannable, 0)
                view.invalidate()
                link.second.onClick(view)
            }
        }
        startIndexOfLink = this.text.toString().indexOf(link.first, startIndexOfLink + 1)
//      if(startIndexOfLink == -1) continue // todo if you want to verify your texts contains links text
        spannableString.setSpan(
            clickableSpan, startIndexOfLink, startIndexOfLink + link.first.length,
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    }
    this.movementMethod =
        LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click
    this.setText(spannableString, TextView.BufferType.SPANNABLE)
}

fun FragmentActivity.showCustomDialog(string: String, status: Boolean, block: () -> Unit) {
    val dialog = SenderDialog(string, status)
    dialog.setOnClickListener {
        block()
    }
    dialog.show(supportFragmentManager, "supportFragmentManager")
}

fun Fragment.checkInternet(): Boolean {
    val type = NetworkUtil.getConnectivityStatus(context)
    return if (type == 0) {
        requireActivity().sendBroadcast(Intent(CONSTANTS.MY_CONNECTIVITY_CHANGE))
        false
    } else {
        true
    }
}

typealias SingleBlock<T> = (T) -> Unit
typealias MultiBlock<T, K> = (T, K) -> Unit
typealias ThreeBlock<T, K, M> = (T, K, M) -> Unit

fun TextInputEditText.isNotEmpty(): Boolean {
    return this.text.toString().isNotEmpty()
}

fun TextInputEditText.isEmpty(): Boolean {
    return this.text.toString().trim().isEmpty()
}

@ColorInt
fun Context.getColorCompat(@ColorRes colorRes: Int): Int = ContextCompat.getColor(this, colorRes)

@ColorInt
fun Fragment.getColorCompat(@ColorRes colorRes: Int): Int = ContextCompat.getColor(requireContext(), colorRes)

@ColorInt
fun FragmentActivity.getColorCompat(@ColorRes colorRes: Int): Int = ContextCompat.getColor(this, colorRes)

@ColorInt
fun Activity.getColorCompat(@ColorRes colorRes: Int): Int = ContextCompat.getColor(this, colorRes)

fun Context.getDrawableCompat(@DrawableRes drawableRes: Int): Drawable? = ContextCompat.getDrawable(this, drawableRes)
fun Fragment.getDrawableCompat(@DrawableRes drawableRes: Int): Drawable? = ContextCompat.getDrawable(requireContext(), drawableRes)
fun FragmentActivity.getDrawableCompat(@DrawableRes drawableRes: Int): Drawable? = ContextCompat.getDrawable(this, drawableRes)
fun Activity.getDrawableCompat(@DrawableRes drawableRes: Int): Drawable? = ContextCompat.getDrawable(this, drawableRes)

fun TextInputEditText.clearText(): View {
    this.text?.clear()
    return this
}

fun String.customMasket(): String {
    val text = this.replace(" ", "")
    var new = ""
    for (i in text.indices) {
        if (i == 4) {
            new += " ("
        }
        if (i == 6) {
            new += ") "
        }

        if (i == 9 || i == 11) {
            new += "-"
        }

        new += text[i]
    }
    return new
}

fun String.customMasketHome(): String {
    val text = this.replace(" ", "")
    var new = ""
    for (i in text.indices) {
        if (i == 4) {
            new += " "
        }
        if (i == 6) {
            new += " "
        }

        if (i == 9 || i == 11) {
            new += "-"
        }
        new += text[i]
    }
    return new
}


fun vibrate(context: Context) {
    val vibrate = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
    vibrate.vibrate(100)
}

fun List<Errors>.getMessage(): String {
    var message = ""
    this.forEach {
        message += "${it.message}\n"
    }
    return message
}

fun String.formatCard(): String {
    return when (this.length) {
        16 -> "${this.substring(0, 4)} ${this.substring(4, 6)}** **** ${this.substring(12, 16)}"
        13 -> "${this.substring(0, 4)} ${this.substring(4, 6)}** **** ${this.substring(9, 13)}"
        else -> this
    }
}

fun String.formatPhone(minus: Boolean = true): String {
    return when (this.length) {
        12 -> getPhoneMasked(this.substring(this.length - 9, this.length), minus)
        9 -> getPhoneMasked(this, minus)
        else -> this
    }
}

fun getPhoneMasked(phone: String, minus: Boolean): String {
    return when {
        phone.length != 9 -> phone
        minus -> "+998 ${phone.substring(0, 2)} ${phone.substring(2, 5)}-${phone.substring(5, 7)}-${phone.substring(7, 9)}"
        else -> "+998 ${phone.substring(0, 2)} ${phone.substring(2, 5)} ${phone.substring(5, 7)} ${phone.substring(7, 9)}"
    }
}

fun ImageView.tint(colorRes: Int) = this.setColorFilter(this.context.color(colorRes))

fun Context.color(colorRes: Int) = ContextCompat.getColor(this, colorRes)
