package com.ydl.ydlcommon.utils

import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.content.res.Resources
import android.content.res.TypedArray
import android.graphics.Rect
import android.os.Build
import android.util.Log
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import java.lang.reflect.Field

/**
 * Created by haorui on 2019/6/11.
 * Des:Android系统相关帮助类
 */
class AndroidSystemHelper {
    companion object {

        //====================修复Android 8.0 崩溃，Only fullscreen activities can request orientation====================
        fun fixAndroidOrientationBug(activity: Activity) {
            if (!isAllowSetOrientation(activity)) {
                val result = resetOrientation(activity)
                Log.i(this.javaClass.simpleName, "onCreate resetOrientation when Oreo, result = " + result);
            }
        }

        /**
         * 反射调用ActivityInfo#isTranslucentOrFloating()
         * 判断当前Activity是否透明or悬浮
         */
        fun isTranslucentOrFloating(activity: Activity): Boolean {
            var isTranslucentOrFloating = false
            try {
                val styleableRes =
                    Class.forName("com.android.internal.R\$styleable").getField("Window").get(null) as IntArray
                val ta = activity.obtainStyledAttributes(styleableRes)
                val m = ActivityInfo::class.java.getMethod("isTranslucentOrFloating", TypedArray::class.java)
                m.isAccessible = true
                isTranslucentOrFloating = m.invoke(null, ta) as Boolean
                m.isAccessible = false
            } catch (e: Exception) {
                e.printStackTrace()
            }

            return isTranslucentOrFloating
        }

        /**
         * 重置屏幕方向
         */
        fun resetOrientation(activity: Activity): Boolean {
            try {
                //设置方向为改为SCREEN_ORIENTATION_UNSPECIFIED：未指定类型
                val field = Activity::class.java.getDeclaredField("mActivityInfo")
                field.isAccessible = true
                val o = field.get(activity) as ActivityInfo
                o.screenOrientation = -1
                field.isAccessible = false
                return true
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return false
        }

        /**
         * 是否允许设置屏幕方向
         */
        fun isAllowSetOrientation(activity: Activity): Boolean {
            return if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating(
                    activity
                )
            ) {
                Log.i(this.javaClass.simpleName, "avoid calling setRequestedOrientation when Oreo.")
                false;
            } else {
                true
            }
        }


        //====================解决 InputMethodManager 导致的内存泄漏问题====================
        fun fixInputMethodManagerLeak(activity: Activity) {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
                return
            }

            val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

            val arr = arrayOf("mCurRootView", "mServedView", "mNextServedView")
            var f: Field?
            var obj_get: Any?
            for (i in arr.indices) {
                val param = arr[i]
                try {
                    f = imm.javaClass.getDeclaredField(param)
                    if (f!!.isAccessible === false) {
                        f!!.isAccessible = true
                    } // author: sodino mail:sodino@qq.com
                    obj_get = f!!.get(imm)
                    if (obj_get != null && obj_get is View) {
                        val v_get = obj_get as View?
                        if (v_get!!.context === activity) { // 被InputMethodManager持有引用的context是想要目标销毁的
                            f.set(imm, null) // 置空，破坏掉path to gc节点
                        } else {
                            // 不是想要目标销毁的，即为又进了另一层界面了，不要处理，避免影响原逻辑,也就不用继续for循环了
                            break
                        }
                    }
                } catch (t: Throwable) {
                    t.printStackTrace()
                }
            }
        }

        //====================解决 修改系统字体大小后 H5页面大小比例不正常现象====================
        fun fixResourcesScale(res: Resources): Resources {
            val config = Configuration()
            config.setToDefaults()
            res.updateConfiguration(config, res.displayMetrics)
            return res
        }

        fun fixAndroidBug5497Workaround(activity: Activity){
            AndroidBug5497Workaround.assistActivity(
                activity
            )
        }
    }

    //================== 解决全屏模式下，“adjustResize”失效问题（Android系统Bug）======================
    /**
     * Des: 解决全屏模式下，“adjustResize”失效问题（Android系统Bug）
     * 链接地址：https://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible/19494006#19494006
     */
    class AndroidBug5497Workaround private constructor(private val activity: Activity) {
        private val mChildOfContent: View
        private var usableHeightPrevious: Int = 0
        private val frameLayoutParams: FrameLayout.LayoutParams
        private var contentHeight: Int = 0
        private var isfirst = true
        private val statusBarHeight: Int

        init {
            //获取状态栏的高度
            val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android")
            statusBarHeight = activity.resources.getDimensionPixelSize(resourceId)
            val content = activity.findViewById<View>(android.R.id.content) as FrameLayout
            mChildOfContent = content.getChildAt(0)

            //界面出现变动都会调用这个监听事件
            mChildOfContent.viewTreeObserver.addOnGlobalLayoutListener {
                if (isfirst) {
                    contentHeight = mChildOfContent.height//兼容华为等机型
                    isfirst = false
                }
                possiblyResizeChildOfContent()
            }

            frameLayoutParams = mChildOfContent.layoutParams as FrameLayout.LayoutParams
        }

        //重新调整跟布局的高度
        private fun possiblyResizeChildOfContent() {

            val usableHeightNow = computeUsableHeight()

            //当前可见高度和上一次可见高度不一致 布局变动
            if (usableHeightNow != usableHeightPrevious) {
                //int usableHeightSansKeyboard2 = mChildOfContent.getHeight();//兼容华为等机型
                val usableHeightSansKeyboard = mChildOfContent.rootView.height
                val heightDifference = usableHeightSansKeyboard - usableHeightNow
                if (heightDifference > usableHeightSansKeyboard / 4) {
                    // keyboard probably just became visible
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                        //frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                        frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight
                    } else {
                        frameLayoutParams.height = usableHeightSansKeyboard - heightDifference
                    }
                } else {
                    frameLayoutParams.height = contentHeight
                }

                mChildOfContent.requestLayout()
                usableHeightPrevious = usableHeightNow
            }
        }

        /**     * 计算mChildOfContent可见高度     ** @return      */
        private fun computeUsableHeight(): Int {
            val r = Rect()
            mChildOfContent.getWindowVisibleDisplayFrame(r)
            return r.bottom - r.top
        }

        companion object {
            fun assistActivity(activity: Activity) {
                AndroidBug5497Workaround(activity)
            }
        }
    }


}
