#define ENABLE_LOG
#define DEBUG
/*
 * Copyright (c) 2014 - 2022 t_saki@serenegiant.com 
 */

using AOT;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using UnityEngine;
#if UNITY_ANDROID && UNITY_2018_3_OR_NEWER
using UnityEngine.Android;
using UnityEngine.Events;
#endif

namespace SLAMUVC
{
    [RequireComponent(typeof(UVCInterface))]
    public class UVCManager : MonoBehaviour
    {
        private const string TAG = "UVCManager#";

        //--------------------------------------------------------------------------------
        public Int32 DefaultWidth = 1280;
        public Int32 DefaultHeight = 720;

        protected UVCInterface _interface;

        /**
		 * 保持正在使用的相机信息
		 */
        public class CameraInfo
        {
            //internal readonly UVCDevice device;
            internal UVCInterface uvcInterface;
            internal Texture previewTexture;
            internal int frameType;
            internal volatile Int32 activeId;
            private Int32 currentWidth;
            private Int32 currentHeight;

            //校准时候使用的分辨率
            Vector2 CalibrationResolution = new Vector2(1280, 720);//"1280x720"; 
            //识别的最高分辨率
            Vector2 HighResolution = new Vector2(320, 240);//"320x240";
            //识别的最低分辨率
            Vector2 LowResolution = new Vector2(160, 120);// "160x120";
            //摄像机参数
            private Dictionary<string, UVCCtrlInfo> ctrlInfos = new Dictionary<string, UVCCtrlInfo>();
            //当前摄像机分辨率
            private Dictionary<string, Vector2> resolutionInfos = new Dictionary<string, Vector2>();

            //PC测试用
            internal CameraInfo(Texture texture)
            {
                // this.device = null;
                activeId = 1;
                previewTexture = texture;
                SetSize(texture.width, texture.height);
            }
            internal CameraInfo(UVCInterface _uvcInterface)
            {
                this.uvcInterface = _uvcInterface;
            }
            /**
             * 是否正在获取图像
             */
            public bool IsPreviewing
            {
                get { return (activeId != 0) && (previewTexture != null); }
            }

            /**
             * 当前分辨率（宽度）
             * 如果不在预览中则为0
             */
            public Int32 CurrentWidth
            {
                get { return currentWidth; }
            }

            /**
             * 当前分辨率（高度）
             * 如果不在预览中则为0
             */
            public Int32 CurrentHeight
            {
                get { return currentHeight; }
            }
            /**
             * 返回一个尺寸
             */
            public Vector2 Size => new Vector2(currentWidth, currentHeight);
            public Vector2Int IndexToCoord(int i)
            {
                var y = i / currentWidth;
                var x = i % currentWidth;
                return new Vector2Int(x, y);
            }

            public int CoordToIndex(int x, int y)
            {
                return y * currentWidth + x;
            }
            /**
             * 修改当前分辨率
             * @param width
             * @param height
             */
            internal bool SetSize(Int32 width, Int32 height)
            {
                bool bChange = false;
                if (width != currentWidth || height != currentHeight)
                {
                    bChange = true;
                    currentWidth = width;
                    currentHeight = height;
                }
                Debug.Log("CameraInfo设置SetSize,大小变化：" + bChange + ",Size：[" + width + "," + height + "]");
                return bChange;
            }
            /**
             * 当前默认分辨率
             */
            public Vector2 CurrentCalibrationResolution
            {
                get { return CalibrationResolution; }
            }
            /**
             * 当前默认校准时候高分辨率
             */
            public Vector2 CurrentHighResolution
            {
                get { return HighResolution; }
            }
            /**
             * 当前默认最低分辨率
             */
            public Vector2 CurrentLowResolution
            {
                get { return LowResolution; }
            }
            /**
              * 修改相机的分辨率，相机分辨率修改成功回调后才修改 本地分辨率
              * @param width
              * @param height
              */
            internal bool SetCameraSize(Int32 width, Int32 height)
            {
                bool bChange = false;
                if (width != currentWidth || height != currentHeight)
                {
                    bChange = true;
                    uvcInterface.ChangeCameraInfo(width, height);
                }
                return bChange;
            }
            /**
             * 更新支持的分辨率
             */
            public void UpdateResolution()
            {
                string[] resolutions = uvcInterface.GetSupportedResolutions();
                resolutionInfos.Clear();
                //resolutions 数组是从大到小
                for (int i = 0; i < resolutions.Length; i++)
                {
                    string resolution = resolutions[i];
                    string[] res = resolution.ToString().Split('x');
                    resolutionInfos.Add(resolution, new Vector2(int.Parse(res[0]), int.Parse(res[1])));
                }
            }


            /**
            * 获取分辨率的key: 1280 * 720
            */
            public List<string> GetResolutionsStrs()
            {
                return new List<string>(resolutionInfos.Keys);
            }

            /**
             * 获取分辨率的values：Vector2(1280,720)
             */
            public List<Vector2> GetResolutionsVec2s()
            {
                return new List<Vector2>(resolutionInfos.Values);
            }
            /**
             * 是否存在分辨率
             */
            public bool ContainsResulutionKey(string type)
            {
                return resolutionInfos.ContainsKey(type);
            }

            /**
             * 更新支持的 UVC 控制/处理功能信息
             */
            public void UpdateCtrls()
            {
                uvcInterface.GetUvcCtrlList();
                ctrlInfos.Clear();
                foreach (UVCCtrl ctrl in uvcInterface.UVCCtrls)
                {
                    // Debug.Log($"name:{ctrl.name}, isAuto: {ctrl.isAuto}, isEnable: {ctrl.isEnable}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}");
                    ctrlInfos.Add(ctrl.name,
                    new UVCCtrlInfo
                    {
                        name = ctrl.name,
                        current = ctrl.value,
                        min = ctrl.limit != null && ctrl.limit.Length > 0 ? ctrl.limit[0] : 0,
                        max = ctrl.limit != null && ctrl.limit.Length > 1 ? ctrl.limit[1] : 0,
                        def = ctrl.limit != null && ctrl.limit.Length > 2 ? ctrl.limit[2] : 0
                    });
                }
            }

            /**
             * 获取支持的 UVC 控制/处理功能的类型列表
             */
            public List<string> GetCtrls()
            {
                return new List<string>(ctrlInfos.Keys);
            }

            /**
             * 获取指定 UVC 控制/处理功能的信息
             * @param type
             * @return UVCCtrlInfo
             * @throws ArgumentOutOfRangeException
             */
            public UVCCtrlInfo GetInfo(string type)
            {
                if (ctrlInfos.ContainsKey(type))
                {
                    return ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
                }
                else
                {
                    throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
                }
            }

            public bool ContainsKey(string type)
            {
                return ctrlInfos.ContainsKey(type);
            }
            /**
             * 获取 UVC 控制/处理功能的设置值
             * @param type
             * @return 变更后的值
             * @throws ArgumentOutOfRangeException
             * @throws Exception
             */
            public Int32 GetValue(string type)
            {
                if (ctrlInfos.ContainsKey(type))
                {
                    var r = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
                    if (r.name != null)
                    {
                        return r.current;
                    }
                    else
                    {
                        throw new Exception($"获取控制值失败,type={type},err={r}");
                    }
                }
                else
                {
                    throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
                }
            }

            /**
             * 修改 UVC 控制/处理功能的设置
             * @param type
             * @param value
             * @return 变更后的值
             * @throws ArgumentOutOfRangeException
             * @throws Exception
             */
            public Int32 SetValue(string type, Int32 value)
            {
                if (ctrlInfos.ContainsKey(type))
                {
                    var r = uvcInterface.SetCtrlValue(type, value);
                    if (r == 0)
                    {
                        UpdateCtrls(); // 同步刷列表
                        var info = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
                        info.current = value;
                        ctrlInfos[type] = info;
                        return value;
                    }
                    else
                    {
                        Debug.LogError($"设置控制值失败,type={type},err={r}");
                    }
                }
                else
                {
                    Debug.LogError($"不支持的控制类型{type:X}");
                }
                return 0;
            }

            public override string ToString()
            {
                return $"{base.ToString()}({currentWidth}x{currentHeight},activeId={activeId},IsPreviewing={IsPreviewing})";
            }

        } // CameraInfo

        /**
         * 获取映像中的 UVC 设备映射
         */
        private CameraInfo cameraInfo;

        /// <summary>
        /// 开始事件
        /// </summary>
        [HideInInspector]
        public UnityEvent<CameraInfo> startUVCManager;
        /// <summary>
        /// 更新事件
        /// </summary>
        [HideInInspector]
        public UnityEvent<bool> updateUVCManager;

        private bool bInit = false;

        private void Awake()
        {
            _interface = GetComponent<UVCInterface>();
            _interface.systemCameraPermissionHandle += () =>
            {
                //授权系统相机之后，初始化红外相机
                initUVCManagerCamera();
            };
        }
        private void Start()
        {
            //initUVCManagerCamera();
        }
        /// <summary>
        /// 初始化相机系统
        /// </summary>
        public void initUVCManagerCamera()
        {
            //初始化相机，连接设备时候自动开启渲染
            _interface.InitCamera(DefaultWidth, DefaultHeight);
            _interface.cameraTextureHandle += () =>
            {
                var info = GetCamera();
                //bChange反馈是否变化宽高
                bool bChange = info.SetSize(_interface.CameraTexture.width, _interface.CameraTexture.height);
                info.previewTexture = _interface.CameraTexture;
                info.activeId = 1;
                if (bInit)
                {
                    //之后的触发的重新创建纹理更新
                    updateUVCManager?.Invoke(bChange);
                }
                else
                {
                    /**
                     * 第一次更新触发初始化
                     */
                    info.UpdateCtrls();//获取摄像机参数
                    info.UpdateResolution();//获取摄像机分辨率
                    startUVCManager?.Invoke(info);
                   // StartCoroutine(DelayGetInfo(info));
                }
                bInit = true;
            };

        }
        /// <summary>
        /// 延迟一下获取操作参数
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        //IEnumerator DelayGetInfo(CameraInfo info)
        //{
        //    yield return new WaitForSecondsRealtime(0.5f);
          
        //}
        /// <summary>
        /// 开启渲染
        /// </summary>
        public void onStartPreview()
        {
            _interface.OpenCamera();
        }
        /// <summary>
        /// 停止渲染
        /// </summary>
        public void onStopPreview()
        {
            _interface.CloseCamera();
            //重置cameraInfo的参数
            var info = GetCamera();
            info.SetSize(0, 0);
            info.previewTexture = null;
            info.activeId = 0;
        }

        /**
         * 获取与指定的 UVC 识别字符串对应的 CameraInfo
         * @param device
         * @return 如果已注册，则返回 CameraInfo；如果未注册，则返回 New CameraInfo
         */
        /*Nullable*/
        private CameraInfo GetCamera()
        {
            if (cameraInfo == null)
                cameraInfo = new CameraInfo(_interface);
            return cameraInfo;
        }


    }
}