using System;
using System.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Rokid.MRC
{
    public class UIPanelBase : MonoBehaviour
    {
        private RectTransform rectTransform;

        public bool FollowCam;
        public float CamDistance = 1.3f;

#if UMR
        public bool UseForUMR;
#endif

        public bool is3DPanel;

        void Update()
        {
            OnUpdate();
        }

        public virtual void OnInit()
        {
            rectTransform = GetComponent<RectTransform>();

            //GraphicRaycaster设置
#if UMR
            //因为Package中没办法获取UXR的类（非Package，并在主工程中），此处暂时用反射的方式添加
            if(UseForUMR)
            {
                BaseRaycaster curRayCaster = GetComponent<GraphicRaycaster>();

                Type tp = curRayCaster.GetType();
                //Type rkType = Type.GetType("Rokid.UXR.RKGraphicRaycaster");

                Assembly assembly = Assembly.GetEntryAssembly();
                assembly = Assembly.GetExecutingAssembly();
                assembly = Assembly.GetCallingAssembly();
                assembly = Assembly.GetAssembly(tp);

                assembly = GetAssembly("Rokid.Unity.XR");

                Type rkType = assembly.GetType("Rokid.UXR.RKGraphicRaycaster");

                if(rkType == null)
                {
                    Debug.LogError("No RKGraphicRaycaster In Project");
                }
                else
                {
                    if(tp != rkType)
                    {
                        Destroy(curRayCaster);

                        gameObject.AddComponent(rkType);
                    }
                }
            }
#endif

            //界面类型
            Canvas canvas = GetComponent<Canvas>();
            if(is3DPanel)
            {
                canvas.renderMode = RenderMode.WorldSpace;
            }
            else
            {
                canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            }
        }

        private Assembly GetAssembly(string name)
        {
            Assembly[] allAssb = AppDomain.CurrentDomain.GetAssemblies();
            for(int i = 0;i < allAssb.Length;i++)
            {
                if(allAssb[i].FullName.Contains(name))
                {
                    return allAssb[i];
                }
            }

            return null;
        }

        public virtual void OnOpen()
        {

        }

        public virtual void OnClose()
        {
        }

        public virtual void OnUpdate()
        {
            if(FollowCam)
            {
                UpdatePanelPose();
            }
        }

        private void UpdatePanelPose()
        {
            if(Camera.main == null)
            {
                return;
            }

            //相机前方多远距离
            Vector3 disPos = Camera.main.transform.forward * CamDistance;
            Vector3 temp = Camera.main.transform.position + disPos;

            //UI界面朝向相机
            transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward);

            //获取整个UI界面4个角的位置
            Vector3[] corners = new Vector3[4];
            rectTransform.GetWorldCorners(corners);
            //判断4个点是否在屏幕内
            if(!IsVisible(corners))
            {
                //不在屏幕内，则缓动到屏幕中
                TweenPosition.Begin(gameObject, transform.position, temp, 0.3f);
            }
            else
            {
                //在屏幕内，则计算UI界面与相机的距离，保持在固定距离
                float dist = Vector3.Distance(transform.position, Camera.main.transform.position);
                if(dist > CamDistance + 0.2f && dist > CamDistance - 0.2f)
                {
                    transform.position = new Vector3(transform.position.x, transform.position.y, temp.z);
                }
            }
        }

        private bool IsVisible(Vector3[] worldPositions)
        {
            int index = 0;
            for(int i = 0;i < worldPositions.Length;i++)
            {
                if(IsGameObjectInCameraView(worldPositions[i]))
                    index++;
            }
            return index >= 3;
        }

        public static bool IsGameObjectInCameraView(Vector3 pos, Camera camera = null)
        {
            if(camera == null)
                camera = Camera.main;

            if(camera == null)
                return false;

            Vector3 targetObjViewportCoord = camera.WorldToViewportPoint(pos);
            if(targetObjViewportCoord.x > 0 && targetObjViewportCoord.x < 1 && targetObjViewportCoord.y > 0f && targetObjViewportCoord.y < 1 && targetObjViewportCoord.z > camera.nearClipPlane && targetObjViewportCoord.z < camera.farClipPlane)
                return true;

            return false;
        }
    }

}