package com.example.vastlib.utils

import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager.NameNotFoundException
import android.os.IBinder
import android.os.IInterface
import android.os.Parcel
import android.os.RemoteException
import android.provider.Settings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.lang.Exception
import java.util.concurrent.LinkedBlockingQueue

@SuppressLint("StaticFieldLeak")
object AndroidIdManager {
    lateinit var context: Context
    var id: String? = null

    fun init(context: Context) {
        this.context = context
    }

    suspend fun getAdId(): String {
        if (id != null) return id!!
        withContext(Dispatchers.IO) {
           try{
                val pm = context.packageManager
                pm.getPackageInfo("com.android.vending", 0)
                val connection = AdvertisingConnection()
                val intent = Intent("com.google.android.gms.ads.identifier.service.START")
                intent.setPackage("com.google.android.gms")
                id =  if (context.bindService(
                        intent,
                        connection,
                        Context.BIND_AUTO_CREATE
                    )
                ) {
                    try {
                        val adInterface = AdvertisingInterface(connection.binder)
                        adInterface.id
                    }catch (e: Exception) {
                        null
                    } finally {
                        context.unbindService(connection)
                    }
                } else {
                   null
                }
               id = if(id == null || id?.contains("00000000") == true) Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) else id
            }catch (e:NameNotFoundException){
                e.printStackTrace()
               id =  Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
            }catch (e:Exception) {

            }
        }
        LogUtils.info("get android Id ${Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)}, $id")
        return id!!
    }

    private class AdvertisingConnection : ServiceConnection {
        var retrieved = false
        private val queue = LinkedBlockingQueue<IBinder>(1)
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            try {
                queue.put(service)
            } catch (ex: InterruptedException) {
                ex.printStackTrace()
            }
        }

        override fun onServiceDisconnected(name: ComponentName) {}

        @get:Throws(InterruptedException::class)
        val binder: IBinder
            get() {
                check(!retrieved)
                retrieved = true
                return queue.take()
            }
    }

    private class AdvertisingInterface internal constructor(private val binder: IBinder) :
        IInterface {
        override fun asBinder(): IBinder {
            return binder
        }

        @get:Throws(RemoteException::class)
        val id: String?
            get() {
                val data = Parcel.obtain()
                val reply = Parcel.obtain()
                val id: String? = try {
                    data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService")
                    binder.transact(1, data, reply, 0)
                    reply.readException()
                    reply.readString()
                } finally {
                    reply.recycle()
                    data.recycle()
                }
                return id
            }
    }
}