using System.Collections.Generic;
using Module.Log;
using UnityEngine;

public class RenderLine
{
    private const string _txSmilePath = "TX_wuhun_01"; //划线端点的特效
    private const string _txBigPath = "TX_wuhun_02"; //划线最后一个端点的特效
    private const string _linePath = "TX_wuhun_03"; // 线段特效组件
    private int _activeCount;
    private int _lastActiveCount;
    // 锁定当前更新
    private bool _lockUpdate;
    private float _WaitLockTime = 0;
    
    private RenderLinePoint[] _linePoints;
    private GameObject _linePrefab;
    private readonly UICameraTexture _uiCameraTexture;

    private Transform _pointPrefab;
    private Transform _endPoint;
    private readonly List<Transform> _middlePoints;
    private readonly List<RenderLineScaler> _lineRenderers;
    private const string _uiCameraLayerName = "UICameraTexture";
    
    public RenderLine(UICameraTexture cameraTexture)
    {
        _middlePoints = new List<Transform>();
        _lineRenderers = new List<RenderLineScaler>();
        _uiCameraTexture = cameraTexture;
        cameraTexture.onModelUpdate += OnUiCameraTextureUpdate;
        InitEffectPrefab();    
    }
    // 切换模型时临时屏蔽当前连线直到新模型加载完成
    // 注:已知问题,无法防御快速切换模型的情况
    public void LockUpdate()
    {
        _lockUpdate = true;

        if(_endPoint!=null)
            _endPoint.gameObject.SetActive(false);
        for (var i = 0; i < _middlePoints.Count; i++)
            _middlePoints[i].gameObject.SetActive(false);
        for (var i = 0; i < _lineRenderers.Count; i++)
            _lineRenderers[i].gameObject.SetActive(false);
    }

    public void UnLockUpdate()
    {
        _lockUpdate = false;
        _WaitLockTime = 1.0f;
    }

    private void InitEffectPrefab()
    {
        // 注:Prefab挂载在_uiCameraTexture下面。有可能特效在摄像机出现前加载成功
        LoadAssetBundle.Instance.LoadGameObject(LoadAssetBundle.BUNDLE_PATH_EFFECT, _txSmilePath,
            (modelName, resObj, hashParam) =>
            {
                // 直接使用resObj作为Prefab源
                if (_pointPrefab == null && resObj != null)
                    _pointPrefab = resObj.transform;
            },
            null);
        
        LoadAssetBundle.Instance.LoadGameObject(LoadAssetBundle.BUNDLE_PATH_EFFECT, _txBigPath,
            (modelName, resObj, hashParam) =>
            {
                if (_endPoint == null && resObj != null)
                {
                    // 复制resObj直接作为实例物体
                    var endPointObj = Object.Instantiate(resObj);
                    endPointObj.SetActive(false);
                    endPointObj.SetLayerRecursively(_uiCameraLayerName);
                    _endPoint = endPointObj.transform;
                    _endPoint.SetParent(_uiCameraTexture.transform, false);
                    _endPoint.localScale = Vector3.one;
                }
            },
            null);
        LoadAssetBundle.Instance.LoadGameObject(LoadAssetBundle.BUNDLE_PATH_EFFECT, _linePath,
            (modelName, resObj, hashParam) =>
            {
                if (_linePrefab == null && resObj != null)
                    _linePrefab = resObj;
            },
            null);
    }
    
    public void LateUpdate()
    {
        // 仅在全部特效加载完成后显示当前内容
        if (_linePrefab != null && _pointPrefab != null && _endPoint != null)
        {
            _lastActiveCount = 0;
            // 隐藏当前显示内容
            if (_lockUpdate || _linePoints == null || _activeCount < 0)
            {
                _endPoint.gameObject.SetActive(false);
                for (var i = 0; i < _middlePoints.Count; i++)
                    _middlePoints[i].gameObject.SetActive(false);
                for (var i = 0; i < _lineRenderers.Count; i++)
                    _lineRenderers[i].gameObject.SetActive(false);
            }
            else
            {
                if(_WaitLockTime>0)
                {
                    _WaitLockTime -= Time.deltaTime;
                    return;
                }
                _endPoint.gameObject.SetActive(true);
                if (_lastActiveCount != _activeCount || _activeCount == 0)
                {
                    _lastActiveCount = _activeCount;
                    for (var i = _lineRenderers.Count; i < _activeCount - 1; i++)
                    {
                        var lineItem = Object.Instantiate(_linePrefab);
                        lineItem.SetLayerRecursively(_uiCameraLayerName);
                        lineItem.layer = _uiCameraTexture.gameObject.layer;
                        lineItem.transform.SetParent(_uiCameraTexture.transform);
                        lineItem.transform.localScale = Vector3.one;
                        lineItem.transform.rotation = Quaternion.identity;
                        var lineRenderer = lineItem.AddComponent<RenderLineScaler>();
                        lineRenderer.Init(_uiCameraTexture._FakeObj.renderCamera.transform, 0.5f);
                        _lineRenderers.Add(lineRenderer);
                    }
                    for (var i = _middlePoints.Count; i < _activeCount - 1; i++)
                    {
                        var middlePoint = Object.Instantiate(_pointPrefab);
                        middlePoint.gameObject.SetLayerRecursively(_uiCameraLayerName);
                        middlePoint.SetParent(_uiCameraTexture.transform);
                        middlePoint.localScale = Vector3.one;
                        middlePoint.rotation = Quaternion.identity;
                        middlePoint.gameObject.layer = _uiCameraTexture.gameObject.layer;
                        _middlePoints.Add(middlePoint);
                    }
                    for (var i = 0; i < _lineRenderers.Count; i++) 
                        _lineRenderers[i].gameObject.SetActive(i < _activeCount - 1);
                    for (var i = 0; i < _middlePoints.Count; i++)
                        _middlePoints[i].gameObject.SetActive(i < _activeCount - 1);
                }
                
                for (var i = 0; i < _activeCount -1; i++)
                {
                    if (i < _linePoints.Length - 1)
                    {
                        _middlePoints[i].position = _linePoints[i].transform.position;
                        _lineRenderers[i].UpdatePoint(_linePoints[i].transform.position, _linePoints[i + 1].transform.position);
                    }
                    else
                        LogModule.WarningLog("模型特效绑定点少于需要激活的绑定点数目!");
                }

                if (_linePoints.Length > 0 && _linePoints.Length >= _activeCount)
                {
                	int index = _activeCount-1;
                	_endPoint.position = _linePoints[index>=0?index:0].transform.position;
                }
            }
        }
    }

    public void SetActivePointCount(int pointCount)
    {
        _activeCount = pointCount;
    }
    
    private void OnUiCameraTextureUpdate(GameObject modelObj)
    {
        if (modelObj == null)
            _lockUpdate = true;
        else
        {
            _lockUpdate = false;
            _WaitLockTime = 1.0f;
            _linePoints = modelObj.GetComponentsInChildren<RenderLinePoint>(true);
            _linePoints.SortArray((a, b) => a.pointIndex.CompareTo(b.pointIndex));
        }
    }
}