package com.example.modifier.utils

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.telephony.PhoneNumberUtils
import android.telephony.SmsManager
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.util.Log
import com.google.gson.Gson
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.UnsupportedEncodingException
import java.nio.charset.StandardCharsets
import java.util.Calendar
import java.util.GregorianCalendar
import kotlin.math.floor

// 获取对应的Intent数据
fun createSmsIntent(number: String, body: String?, slot: Int, subId: Int): Intent {
    val smsManager = SmsManager.getDefault()
    // 防止短信过长
    val messages = smsManager.divideMessage(body)
    val size = messages.size
    val objArray = arrayOfNulls<ByteArray>(size)
    for (i in 0 until size) {
        val pduu = createFakeSms(number, messages[i])
        objArray[i] = pduu
    }
    val intent = Intent()
    intent.setAction("android.provider.Telephony.SMS_DELIVER")

    intent.putExtra("android.telephony.extra.SUBSCRIPTION_INDEX", subId)
    intent.putExtra(
        "messageId", floor(Math.random() * 100000000)
            .toInt().toLong()
    )
    intent.putExtra("pdus", objArray)
    intent.putExtra("format", "3gpp")
    intent.putExtra("android.telephony.extra.SLOT_INDEX", slot)
    intent.putExtra("phone", slot)
    intent.putExtra("subscription", subId)
    return intent
}

@SuppressLint("MissingPermission")
fun createSmsIntent(context: Context, number: String, body: String?): Intent {
    val telephonyManager =
        context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    val subscriptionManager = context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
    val simCount = subscriptionManager.activeSubscriptionInfoCountMax
    var subId = 0
    var slot = 0
    for (i in 0 until simCount) {
        val subInfo = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(i)
        if (subInfo != null) {
            Log.d(com.example.modifier.baseTag, "subId: " + subInfo.subscriptionId)
            subId = subInfo.subscriptionId
            slot = subInfo.simSlotIndex
            break
        }
    }

    return createSmsIntent(number, body, slot, subId)
}

// 创建pdu
fun createFakeSms(sender: String, body: String): ByteArray? {
    var pdu: ByteArray? = null
    val scBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD("0000000000")
    val senderBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(sender)
    val lsmcs = scBytes.size
    // 时间处理，包括年月日时分秒以及时区和夏令时
    val dateBytes = ByteArray(7)
    val calendar: Calendar = GregorianCalendar()
    dateBytes[0] = reverseByte(calendar[Calendar.YEAR].toByte())
    dateBytes[1] = reverseByte((calendar[Calendar.MONTH] + 1).toByte())
    dateBytes[2] = reverseByte(calendar[Calendar.DAY_OF_MONTH].toByte())
    dateBytes[3] = reverseByte(calendar[Calendar.HOUR_OF_DAY].toByte())
    dateBytes[4] = reverseByte(calendar[Calendar.MINUTE].toByte())
    dateBytes[5] = reverseByte(calendar[Calendar.SECOND].toByte())
    dateBytes[6] = reverseByte(
        ((calendar[Calendar.ZONE_OFFSET]
                + calendar[Calendar.DST_OFFSET]) / (60 * 1000 * 15)).toByte()
    )
    try {
        val bo = ByteArrayOutputStream()
        bo.write(lsmcs) // 短信服务中心长度
        bo.write(scBytes) // 短信服务中心号码
        bo.write(0x04)
        bo.write(sender.length.toByte().toInt()) // 发送方号码长度
        bo.write(senderBytes) // 发送方号码
        bo.write(0x00) // 协议标示，00为普通GSM，点对点方式
        try {
            val className = "com.android.internal.telephony.GsmAlphabet"
            val clazz = Class.forName(className)
            val method = clazz.getMethod(
                "stringToGsm7BitPacked", *arrayOf<Class<*>>(
                    String::class.java
                )
            )
            method.isAccessible = true
            val bodybytes = method.invoke(null, body) as ByteArray

            bo.write(0xf1) // encoding: 0 for default 7bit
            bo.write(dateBytes)
            bo.write(bodybytes)
        } catch (e: Exception) {
            // 下面是UCS-2编码的处理，中文短信就需要用此种方式
            val bodyBytes = encodeUCS2(body, null)
            bo.write(0x08) // encoding: 8 for UCS-2
            bo.write(dateBytes)
            bo.write(bodyBytes) // 其中encodeUCS2是从系统中复制过来的，并不是我写的
            // 源码具体位置在
            // frameworks/base/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
        }

        pdu = bo.toByteArray()
    } catch (e: IOException) {
    }
    return pdu
}

private fun reverseByte(b: Byte): Byte {
    return ((b.toInt() and 0xF0) shr 4 or ((b.toInt() and 0x0F) shl 4)).toByte()
}

@Throws(UnsupportedEncodingException::class)
private fun encodeUCS2(message: String, header: ByteArray?): ByteArray {
    val userData: ByteArray
    val textPart = message.toByteArray(StandardCharsets.UTF_16BE)

    if (header != null) {
        // Need 1 byte for UDHL
        userData = ByteArray(header.size + textPart.size + 1)

        userData[0] = header.size.toByte()
        System.arraycopy(header, 0, userData, 1, header.size)
        System.arraycopy(textPart, 0, userData, header.size + 1, textPart.size)
    } else {
        userData = textPart
    }
    val ret = ByteArray(userData.size + 1)
    ret[0] = (userData.size and 0xff).toByte()
    System.arraycopy(userData, 0, ret, 1, userData.size)
    return ret
}

fun toGson(obj: Any?): String {
    val gson = Gson()
    return gson.toJson(obj)
}