using System.Text.Json.Nodes;
using SharpDX;
using SparkClient.Views.UserControl.ViewportData.Entity;
using SparkClient.Views.UserControl.ViewportData.Enum;
using SparkClient.Views.UserControl.ViewportData.Helper;

namespace SparkClient.Views.UserControl.ViewportData;

public class ViewportData
{
    /// <summary>
    /// 钻石编码
    /// </summary>
    public String DiamondCode { get; set; }
    
    /// <summary>
    /// 钻石数据
    /// </summary>
    public String DiamondData { get; set; }

    public ColorConfigEntity ColorConfig { get; set; } = new ColorConfigEntity();

    /// <summary>
    /// 初始化构造
    /// </summary>
    /// <param name="diamondCode">钻石编码</param>
    /// <param name="diamondData">钻石数据</param>
    public ViewportData(string diamondCode, string diamondData)
    {
        DiamondCode = diamondCode;
        DiamondData = diamondData;
    }
    /// <summary>
    /// 初始化构造
    /// </summary>
    /// <param name="diamondCode">钻石编码</param>
    /// <param name="diamondData">钻石数据</param>
    public ViewportData(string diamondCode, string diamondData, ColorConfigEntity colorConfig)
    {
        DiamondCode = diamondCode;
        DiamondData = diamondData;
        ColorConfig = colorConfig;
    }
    /// <summary>
    /// 空白构造
    /// </summary>
    public ViewportData()
    {
    }

    public void LoadData()
    {
        JsonNode? json = null;
        try
        {
            json = JsonNode.Parse(DiamondData);
        }
        catch
        {
            throw new Exception("DiamondData is invalid");
        }
        
        if(json == null) throw new Exception("DiamondData is invalid");
        
        try
        {
            List<Viewport3DTriangleEntity> facets = new List<Viewport3DTriangleEntity>();
            if (json.AsObject()["facets"] != null)
            {
                JsonArray jsonArray = json.AsObject()["facets"].AsArray();
                foreach (var item in jsonArray)
                {
                    var value = CommonHelper.CreateByJsonStr(item.ToString());
                    facets.Add(value);
                }
            }
            else
            {
                throw new Exception("facets is invalid");
            }

            if (json.AsObject()["positive_direction"] != null)
            {
                JsonObject positive = json.AsObject()["positive_direction"].AsObject();
                ViewportManager.PositiveDirection.X = float.Parse(positive["x"]?.ToString() ?? "1.0");
                ViewportManager.PositiveDirection.Y = float.Parse(positive["z"]?.ToString() ?? "0");
                ViewportManager.PositiveDirection.Z = float.Parse(positive["y"]?.ToString() ?? "0");
            }
            else
            {
                ViewportManager.PositiveDirection.X = 1.0f;
                ViewportManager.PositiveDirection.Y = 0f;
                ViewportManager.PositiveDirection.Z = 0;
            }
            
            var measurements = json.AsObject()["measurements"];
            ViewportManager.DiamondData = measurements==null?new JsonObject():measurements.AsObject();
            var midZ = facets.SelectMany(e => new[] { e.Point1.X, e.Point2.X, e.Point3.X }).OrderBy(z => Math.Abs(z))
                .First();
            List<Viewport3DTriangleEntity> facetsFinal = new List<Viewport3DTriangleEntity>();
            foreach (var item in facets)
            {
                var data = ViewportHelperPro.VectorClockwiseSort(new List<Vector3>
                    { item.Point1, item.Point2, item.Point3 });

                if (item.PlaneType == PlaneType.StarFacet || item.PlaneType == PlaneType.UpperGirdleFacet ||
                    item.PlaneType == PlaneType.UpperMainFacet || item.PlaneType == PlaneType.TableFacet)
                {
                    item.Point1 = data[0];
                    item.Point2 = data[1];
                    item.Point3 = data[2];
                }
                else if (item.PlaneType == PlaneType.Girdle)
                {
                    var center = ViewportHelperPro.GetCentroid(data);
                    data.Sort((v1, v2) =>
                    {
                        double angle1 = Math.Atan2(v1.Y - center.Y, v1.X - center.X);
                        double angle2 = Math.Atan2(v2.Y - center.Y, v2.X - center.X);
                        return angle1.CompareTo(angle2);
                    });
                    if (center.Z >= midZ)
                    {

                        item.Point1 = data[0];
                        item.Point2 = data[1];
                        item.Point3 = data[2];
                    }
                    else
                    {
                        item.Point1 = data[2];
                        item.Point2 = data[1];
                        item.Point3 = data[0];

                    }
                }
                else
                {
                    item.Point1 = data[2];
                    item.Point2 = data[1];
                    item.Point3 = data[0];
                }

                item.TriangleCode = CommonHelper.GenerateTriangleCode(item.Point1, item.Point2, item.Point3);
                facetsFinal.Add(item);
            }

            ViewportManager.ViewportTriangle.Clear();
            ViewportManager.ViewportTriangle.AddRange(facetsFinal);
            ViewportManager.ColorConfig = ColorConfig;
            // ViewportManager.LoadModelByEntities(facetsFinal);
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }


    public async Task SaveAsToStlFile(string filename)
    {
        try
        {
            await ViewportHelperPro.ExportModelsToStlASync(filename);
            return ;
        }
        catch
        {
            return ;
        }
    }

    public async Task SaveAsToVedioFile(string filename)
    {
        try
        {
            await ViewportHelperPro.ExportModelsToVideo(null, filename);
        
        }
        catch
        {
            return ;
        }
    }

    public bool ConvertMp4ToDat(string mp4FilePath, string datFilePath)
    {
       
        try
        {
            VideoHelper.ConvertMp4ToDat(datFilePath, mp4FilePath);
            return true;
        }
        catch
        {
            return false;
        }
    }

    public void mockSel(string planKey)
    {
        ViewportManager.MockSelectFacet(planKey);
    }
    
}