using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;
using UnityEngine.Rendering;
using UnityEngine.UI;
using Utility;

[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
public class UIObject : MaskableGraphic, IMeshModifier
{
    public static Map<Shader, List<string>> allShaderName = new Map<Shader, List<string>>();
    private MaterialPropertyBlock MaterialPropertyBlock;
    public Material _material;
    public Mesh _Mesh;

    public bool isNewMaterial;
    private Renderer _renderer;

    public Camera Camera;

    // public
    public override Material defaultMaterial
    {
        get { return _material; }
    }

    protected override void OnEnable()
    {
        canvasRenderer.Clear();
        base.OnEnable();
    }

    protected override void OnDisable()
    {
        canvasRenderer.Clear();
        base.OnDisable();
    }

    protected override void Awake()
    {
        base.Awake();
        _renderer = gameObject.GetComponent<Renderer>();
        if (_renderer == null)
        {
            return;
        }

        _renderer.enabled = false;
        if (isNewMaterial)
        {
            _material = new Material(_renderer.sharedMaterial);
        }
        else
        {
            _material = _renderer.sharedMaterial;
        }

      

        // _material.shader.p
        _Mesh = gameObject.GetComponent<MeshFilter>().sharedMesh;
        if (_Mesh != null)
        {
            List<Vector3> nor = new List<Vector3>();
            for (int i = 0; i < _Mesh.colors.Length; i++)
            {
                nor.Add(new Vector3(_Mesh.colors[i].r, _Mesh.colors[i].g, 0));
            }

            _Mesh.normals = nor.ToArray();
        }
    }

    public override void Rebuild(CanvasUpdate update)
    {
        base.Rebuild(update);
        if (update == CanvasUpdate.PreRender)
        {
        }
    }

    private void Update()
    {
        if (_material == null)
        {
            return;
        }

        if (MaterialPropertyBlock == null)
        {
            MaterialPropertyBlock = new MaterialPropertyBlock();
        }

        _renderer.GetPropertyBlock(MaterialPropertyBlock);
        Shader shader = _material.shader;
        if (!allShaderName.TryGetValue(shader, out List<string> keyName))
        {
            keyName = new List<string>();
            for (int i = 0; i < _material.shader.GetPropertyCount(); i++)
            {
                string name = _material.shader.GetPropertyName(i);
                keyName.Add(name);
            }

            allShaderName.Add(shader, keyName);
        }


        for (int i = 0; i < keyName.Count; i++)
        {
            string name = keyName[i];
            if (name != null && MaterialPropertyBlock.HasProperty(name))
            {
                if (_material.shader.GetPropertyType(i) == ShaderPropertyType.Color)
                {
                    _material.SetColor(name, MaterialPropertyBlock.GetColor(name));
                }

                if (_material.shader.GetPropertyType(i) == ShaderPropertyType.Float)
                {
                    _material.SetFloat(name, MaterialPropertyBlock.GetFloat(name));
                }

                if (_material.shader.GetPropertyType(i) == ShaderPropertyType.Range)
                {
                    _material.SetFloat(name, MaterialPropertyBlock.GetFloat(name));
                }

                if (_material.shader.GetPropertyType(i) == ShaderPropertyType.Vector)
                {
                    _material.SetVector(name, MaterialPropertyBlock.GetVector(name));
                }

                if (_material.shader.GetPropertyType(i) == ShaderPropertyType.Int)
                {
                    _material.SetInt(name, MaterialPropertyBlock.GetInt(name));
                }

                if (_material.shader.GetPropertyType(i) == ShaderPropertyType.Texture)
                {
                    _material.SetTexture(name, MaterialPropertyBlock.GetTexture(name));
                }
            }
        }
    }


    protected override void UpdateMaterial()
    {
        if (!IsActive())
            return;
        canvasRenderer.materialCount = 1;
        canvasRenderer.SetMaterial(materialForRendering, 0);
    }

    [ContextMenu("刷新mesh")]
    public void ShuaXing()
    {
        // _Mesh = gameObject.GetComponent<MeshFilter>().sharedMesh;
        SetAllDirty();
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        base.OnPopulateMesh(vh);
    }

    private bool isAlater = false;

    protected override void UpdateGeometry()
    {
        // if (rectTransform != null )
        //     OnPopulateMesh(s_VertexHelper);
        //
        //
        // var components = ListPool<Component>.Get();
        // GetComponents(typeof(IMeshModifier), components);
        //    
        // for (var i = 0; i < components.Count; i++)
        //     ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper);
        //
        // ListPool<Component>.Release(components);
        //
        // s_VertexHelper.FillMesh(workerMesh);
        // canvasRenderer.SetMesh(workerMesh);
        // if (isAlater)
        // {
        //     return;
        // }
        //
        // isAlater = true;
        if (_renderer is LineRenderer)
        {
            LineRenderer lineRenderer = _renderer as LineRenderer;
            _Mesh = new Mesh();
            if (Camera == null)
            {
                Canvas canvas = transform.GetComponentInParent<Canvas>();
                if (canvas != null)
                {
                    Camera = canvas.worldCamera;
                }
            }

            if (Camera == null)
            {
                return;
            }
   
            lineRenderer.BakeMesh(_Mesh, Camera, transform);
            List<Vector3> nor = new List<Vector3>();
            for (int i = 0; i < _Mesh.colors.Length; i++)
            {
                nor.Add(new Vector3(_Mesh.colors[i].r, _Mesh.colors[i].g, 0));
            }

            _Mesh.normals = nor.ToArray();
        }

      
        canvasRenderer.SetMesh(_Mesh);
    }

    // protected override void OnPopulateMesh(VertexHelper vh)
    // {
    //     base.OnPopulateMesh(vh);
    // }

    public void ModifyMesh(Mesh mesh)
    {
    }

    public void ModifyMesh(VertexHelper verts)
    {
        UIVertex vertex = new UIVertex();
        for (int i = 0; i < verts.currentVertCount; i++)
        {
            verts.PopulateUIVertex(ref vertex, i);
            vertex.color = _Mesh.colors[i];
            vertex.normal = new Vector3(vertex.color.r, vertex.color.g);
            verts.SetUIVertex(vertex, i);
        }
    }
}