using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

struct RequiredInformation//提供参数来生成浮标
{

    public string SNWithdeviceName;
    public Vector3 localPosition;
    public string customName;//这个是浮标上面的文本，自己命的名
    public string pictureSerialNumber;//MT开头的图片
    public string tag;//用tag来显示sorting Icons
    public RequiredInformation(string sn, Vector3 pos, string name, string picSn,string tag)
    {
        SNWithdeviceName = sn;
        localPosition = pos;
        customName = name;
        pictureSerialNumber = picSn;
        this.tag = tag;
    }
    public RequiredInformation(string sn, string name, string picSn, string tag)
    {
        SNWithdeviceName = sn;
        localPosition = Vector3.zero;
        customName = name;
        pictureSerialNumber = picSn;
        this.tag = tag;
    }
}
public class AskForWEBInfomation : MonoBehaviour
{
    public GameObject ICONSPosition;//把ICONSPosition拖进来提供我的这些浮标的位置
    public Camera cam;

    public GameObject buoy;//把BUoy预制体拖进来，使用代码自动生成ICON的子物体

  //  public List<Sprite> pictures = new List<Sprite>();//把图片预制体都拖过来
   /* [Serializable]
    public class IdentifierTextBinding
    {
        public string identifier;
        public TMP_Text targetText;
    }*/

    [Header("认证")]
    [TextArea(2, 4)]
     string authorization = "tenantCode=DEMO&accessToken=225e1a7ffede96cb5adab3aa98775660f4c6a066";

    [Header("编辑器测试地址")]
    string editorFullUrl = "https://3d.gzckgc.cn/api.php/Device/deviceDetail";

    [Header("设备SN列表")]
    public List<string> deviceSnList = new List<string>
    {

        "ys_2026020420","ys_2026020419","ys_2026020418","ys_2026020417","ys_2026020416","ys_2026020415"
    };
    List<RequiredInformation> infos = new List<RequiredInformation>()
    { //构造函数现在可以使用4参数构造，
        new RequiredInformation("ys_2026042701_sb_duopule001","流量计1","MT019","流量监测") ,
        new RequiredInformation("ys_2026042702_sb_duopule002","流量计2","MT019","流量监测") ,
        new RequiredInformation("ys_2026042703_sb_duopule003","流量计3","MT019","流量监测") ,
        new RequiredInformation("ys_2026042704_sb_duopule004","流量计4","MT019","流量监测") ,
        new RequiredInformation("ys_2026042705_sb_duopule005","流量计5","MT019","流量监测") ,
        new RequiredInformation("ys_2026042701_sb_leidashuiweiji001","雷达水位计1","MT011RainfallANDWaterlevel","水位监测") ,
        new RequiredInformation("ys_2026042702_sb_leidashuiweiji002","雷达水位计2","MT011RainfallANDWaterlevel","水位监测") ,
        new RequiredInformation("ys_2026042703_sb_leidashuiweiji003","雷达水位计3","MT011RainfallANDWaterlevel","水位监测") ,
        new RequiredInformation("ys_2026042704_sb_leidashuiweiji004","雷达水位计4","MT011RainfallANDWaterlevel","水位监测") ,
        new RequiredInformation("ys_2026042705_sb_leidashuiweiji005","雷达水位计5","MT011RainfallANDWaterlevel","水位监测") ,
        new RequiredInformation("ys_2026042701_sb_shuizhi_diandaolv001","电导率1","水质","水质监测") ,
        new RequiredInformation("ys_2026042702_sb_shuizhi_diandaolv002","电导率2","水质","水质监测") ,
        new RequiredInformation("ys_2026042703_sb_shuizhi_diandaolv003","电导率3","水质","水质监测") ,
        new RequiredInformation("ys_2026042704_sb_shuizhi_diandaolv004","电导率4","水质","水质监测") ,
        new RequiredInformation("ys_2026042705_sb_shuizhi_diandaolv005","电导率5","水质","水质监测") ,
        new RequiredInformation("ys_2026042701_sb_shuizhi_PH001","pH1","水质","水质监测") ,
        new RequiredInformation("ys_2026042702_sb_shuizhi_PH002","pH2","水质","水质监测") ,
        new RequiredInformation("ys_2026042703_sb_shuizhi_PH003","pH3","水质","水质监测") ,
        new RequiredInformation("ys_2026042704_sb_shuizhi_PH004","pH4","水质","水质监测") ,
        new RequiredInformation("ys_2026042705_sb_shuizhi_PH005","pH5","水质","水质监测") ,
        new RequiredInformation("ys_2026042701_sb_shuizhi_zhuodu001","浊度1","水质","水质监测") ,
        new RequiredInformation("ys_2026042702_sb_shuizhi_zhuodu002","浊度2","水质","水质监测") ,
        new RequiredInformation("ys_2026042703_sb_shuizhi_zhuodu003","浊度3","水质","水质监测") ,
        new RequiredInformation("ys_2026042704_sb_shuizhi_zhuodu004","浊度4","水质","水质监测") ,
        new RequiredInformation("ys_2026042705_sb_shuizhi_zhuodu005","浊度5","水质","水质监测") 

    };


    

   /* [Header("手动拖拽绑定：identifier -> TMP_Text")]
    public List<IdentifierTextBinding> bindings = new List<IdentifierTextBinding>();*/

    [Header("显示设置")]
    public string valueFormat = "0.##";
    public bool includeUnit = true;

    private Dictionary<string, TMP_Text> textMap = new Dictionary<string, TMP_Text>();


    public bool _isRunning = false;//这个东西只是用来防止手动连点
    private void Awake()
    {
        cam = Camera.main;
        InitiateICONS();
        //BuildBindingMap();
    }
    private void InitiateICONS()
    {
        //使用 info 之前要先用 ICONPosition 来调整一下里面的位置,用 foreach 还不能改，只能用 for 循环慢慢改回去
        for (int i = 0; i < infos.Count; i++)
        {
            RequiredInformation info = infos[i];
            
            info.localPosition = ICONSPosition.transform.Find(info.SNWithdeviceName).localPosition;
            infos[i] = info;
        }

        //开始用修改好的infos来工作
        foreach (RequiredInformation info in infos)
        {
            //生成一个预制体
            GameObject obj = Instantiate(buoy);
            obj.name = info.SNWithdeviceName;
            obj.transform.SetParent(transform);
            obj.transform.localPosition = info.localPosition;
            obj.tag = info.tag;//添加标签

            //开始修理预制体下面的响应函数和text
            int first = obj.name.IndexOf("_");
            int second = obj.name.IndexOf('_', first + 1);//second 是第二个下划线的索引，索引是从0开始的
            string deviceSn = obj.name.Substring(0, second);//前半部分，比如ys_2026030415,末尾没有下划线，但是这部分不重要，重要的是后半部分。
                                                            //这里second表示长度，第二个下划线索引是9，也就是第10位，但是索引做长度正好把第十位丢掉了
            string deviceName = obj.name.Substring(second + 1);     //设备名，也就是后半部分，从指定索引开始到结尾
            //第一个子物体主要负责浮标的响应函数
            obj.transform.GetChild(0).name = deviceName + "ICON";
            obj.transform.GetChild(0).GetComponent<Button>().onClick.RemoveAllListeners();
            obj.transform.GetChild(0).GetComponent<Button>().onClick.AddListener(
                () => {
                    cam.GetComponent<DoubleClickToFocus>().FlyToIconAndConvertCore(obj.transform.GetChild(0).name);
                }
                );
            obj.transform.GetChild(0).GetComponent<Button>().onClick.AddListener(
               () => {
                   ManuallyLoadOneDevice(obj.name);
               }
               );
            /* foreach (Sprite img in pictures)//遍历图片数组，如果找到就结束,现在改成用 Resources 直接加载
             {
                 if (img.name == info.pictureSerialNumber)
                 {
                     obj.transform.GetChild(0).GetComponent<Image>().sprite = img;
                     break;
                 }
             }*/
            obj.transform.GetChild(0).GetComponent<Image>().sprite = Resources.Load<Sprite>("Icons/"+info.pictureSerialNumber);

            //第二个子物体负责浮标上面的文字描述
            obj.transform.GetChild(1).name = deviceName + "Text";
            obj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = info.customName;
        }
    }
 /*  private void BuildBindingMap()
    {
        textMap.Clear();

        foreach (var binding in bindings)
        {
            if (binding == null) continue;
            if (string.IsNullOrWhiteSpace(binding.identifier)) continue;
            if (binding.targetText == null) continue;

            textMap[binding.identifier] = binding.targetText;
        }
    }*/
    private void Start()
    {
        StartCoroutine(LoadAllDevices());
    }
    //这个是和前端交互的时候按下的按钮
    public void ManuallyLoadOneDevice(string SnWithDeviceName)
    {

        if (_isRunning)
            return;

        StartCoroutine(LoadOneDeviceManually(SnWithDeviceName));

    }
    IEnumerator DelayPart()
    {
        yield return new WaitForSeconds(2.0f); // 等待2秒

        // 这里写延迟执行的代码
        Debug.Log("2秒后执行");
    }
    private IEnumerator LoadAllDevices()
    {
        if (string.IsNullOrWhiteSpace(authorization) || authorization.Contains("替换"))
        {
            Debug.LogError("authorization 还没填。");
            yield break;
        }

        foreach (string sn in deviceSnList)
        {
            yield return StartCoroutine(LoadOneDevice(sn));
        }

        Debug.Log("全部设备文本更新完成");
    }


    private IEnumerator LoadOneDevice(string deviceSn)
    {
        string url = GetRequestUrl();

        WWWForm form = new WWWForm();
        form.AddField("device_sn", deviceSn);

        using (UnityWebRequest req = UnityWebRequest.Post(url, form))
        {
            req.SetRequestHeader("Accept", "application/json, text/plain, */*");
            req.SetRequestHeader("Authorization", authorization);

            yield return req.SendWebRequest();

            if (req.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"请求失败 | SN={deviceSn} | {req.error}");
                yield break;
            }

            string json = req.downloadHandler.text;

            DeviceDetailResponse resp = null;
            try
            {
                resp = JsonUtility.FromJson<DeviceDetailResponse>(json);
            }
            catch (Exception e)
            {
                Debug.LogError($"JSON解析失败 | SN={deviceSn} | {e.Message}");
                yield break;
            }

            if (resp == null || resp.status == null)
            {
                Debug.LogError($"响应为空 | SN={deviceSn}");
                yield break;
            }



            if (resp.status.code != 0)
            {
                Debug.LogError($"业务失败 | SN={deviceSn} | code={resp.status.code} | msg={resp.status.msg}");
                yield break;
            }

            if (resp.result == null || resp.result.data_points == null || resp.result.data_points.timeseries == null)
            {
                Debug.LogWarning($"没有 timeseries 数据 | SN={deviceSn}");
                yield break;
            }

            foreach (DevicePoint point in resp.result.data_points.timeseries)
            {
                if (point == null) continue;
                if (string.IsNullOrWhiteSpace(point.identifier)) continue;

               // UpdateText(point.identifier, point.value, point.unitName, point.name);

            }
        }
    }

    private IEnumerator LoadOneDeviceManually(string deviceSnWithName)//狗日的unity多参数不能用inspector编辑,重载还不能名字相同，烦。。
    {

        _isRunning = true;
        yield return null;
        float transitionDuration = Camera.main.transform.GetComponent<DoubleClickToFocus>().transitionDuration;
        yield return new WaitForSeconds(transitionDuration + 0.01f); // 等待2秒

        // 这里写延迟执行的代码
        Debug.Log("2秒后执行");

        //为了手动点击传出sn和传感器名字，命名ys_2026020427_sb_wuxianqingjiaoji001，这样，用下划线找sn和名字
        //我给这个方法重载了，
        //分别是手动点击时和自动跳转
        //唯一不同就是最下面判断是不是被点击的设备
        int first = deviceSnWithName.IndexOf("_");
        int second = deviceSnWithName.IndexOf('_', first + 1);
        string deviceSn = deviceSnWithName.Substring(0, second);
        string iconName = GameObject.Find("ICONS").transform.Find(deviceSnWithName).transform.Find(deviceSnWithName.Substring(second + 1) + "Text").GetComponent<TextMeshProUGUI>().text;
        //传感器的名字。用这个 object 里面的 text。无法用 gameobject. find 直接找到子对象，先找它的父对象，然后用父对象找子对象。
        string url = GetRequestUrl();

        WWWForm form = new WWWForm();
        form.AddField("device_sn", deviceSn);

        using (UnityWebRequest req = UnityWebRequest.Post(url, form))
        {
            req.SetRequestHeader("Accept", "application/json, text/plain, */*");
            req.SetRequestHeader("Authorization", authorization);

            yield return req.SendWebRequest();

            if (req.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"请求失败 | SN={deviceSn} | {req.error}");
                yield break;
            }

            string json = req.downloadHandler.text;

            DeviceDetailResponse resp = null;
            try
            {
                resp = JsonUtility.FromJson<DeviceDetailResponse>(json);
            }
            catch (Exception e)
            {
                Debug.LogError($"JSON解析失败 | SN={deviceSn} | {e.Message}");
                yield break;
            }

            if (resp == null || resp.status == null)
            {
                Debug.LogError($"响应为空 | SN={deviceSn}");
                yield break;
            }
            //此部分为手动获取数据和自动获取数据的唯一区别。
            SendData sendData = new SendData();
            sendData.result = resp.result;
            sendData.iconName = iconName;
            string CoutJsonData = JsonUtility.ToJson(sendData, true);
            Application.ExternalCall("sendDataToVue", CoutJsonData);
            //Debug.Log(CoutJsonData);

            if (resp.status.code != 0)
            {
                Debug.LogError($"业务失败 | SN={deviceSn} | code={resp.status.code} | msg={resp.status.msg}");
                yield break;
            }

            if (resp.result == null || resp.result.data_points == null || resp.result.data_points.timeseries == null)
            {
                Debug.LogWarning($"没有 timeseries 数据 | SN={deviceSn}");
                yield break;
            }

            foreach (DevicePoint point in resp.result.data_points.timeseries)
            {
                if (point == null) continue;
                if (string.IsNullOrWhiteSpace(point.identifier)) continue;

               // UpdateText(point.identifier, point.value, point.unitName, point.name);


            }
        }
        _isRunning = false;//协程运行完成自动解锁。
        Debug.Log("单次查询完成");
    }

    private void UpdateText(string identifier, string valueStr, string unitName, string itemName)
    {
        if (!textMap.TryGetValue(identifier, out TMP_Text target) || target == null)
        {
            Debug.LogWarning($"没有绑定 identifier: {identifier}");
            return;
        }

        string finalText = valueStr;

        if (float.TryParse(valueStr, NumberStyles.Any, CultureInfo.InvariantCulture, out float value))
        {
            finalText = value.ToString(valueFormat, CultureInfo.InvariantCulture);
        }

        if (includeUnit)//&& !string.IsNullOrWhiteSpace(unitName)
        {
            finalText += unitName;
            finalText = itemName + ": " + finalText;
        }

        target.text = finalText;
    }

    private string GetRequestUrl()
    {
#if UNITY_WEBGL && !UNITY_EDITOR
        return "/api.php/Device/deviceDetail";
#else
        return editorFullUrl;
#endif
    }

   /* [ContextMenu("重建绑定字典")]
    private void RebuildBindings()
    {
        BuildBindingMap();
        Debug.Log("绑定字典已重建");
    }*/

    [Serializable]
    public class DeviceDetailResponse
    {
        public ApiStatus status;
        public DeviceResult result;
    }

    [Serializable]
    public class ApiStatus
    {
        public int code;
        public string msg;
    }

    [Serializable]
    public class DeviceResult
    {
        public int device_id;
        public string device_name;
        public string device_sn;
        public string status;
        public string online_status;
        public string location;
        public string address;
        public string pic;
        public DataPoints data_points;
    }
    [Serializable]
    public class SendData
    {
        public string iconName;
        public DeviceResult result;

    }
    [Serializable]
    public class DataPoints
    {
        public DevicePoint[] control;
        public DevicePoint[] timeseries;
    }

    [Serializable]
    public class DevicePoint
    {
        public string point_id;
        public string name;
        public string alias;
        public string identifier;
        public string unitName;
        public string unitIdentifier;
        public string accessMode;
        public string dataType;
        public string value;
        public string callback_time;
    }
}