using SimpleCore.PropType;
using SimpleCore;
using System.Collections.Generic;
using System.Dynamic;
using Simple3.CADTools;
using Simple3.Props;
using Simple3.UI;
using System.Numerics;
using System.Drawing;
using System;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Simple3.RCS;
using Simple3.RCS.CarTypes;

namespace StandardScene.Model
{
    public class Map
    {
        public List<ExpandoObject> Sites { get; set; }
        public List<ExpandoObject> Tracks { get; set; }
        public List<ExpandoObject> CircularArcTracks { get; set; }
        public List<ExpandoObject> BezierTracks { get; set; }

        public static Map GetMap()
        {
            var map = new Map
            {
                Sites = new List<ExpandoObject>()
            };
            Site[] allSites = SimpleLib.GetAllSites();
            foreach (var site in allSites)
            {
                dynamic theSite = new ExpandoObject();
                theSite.Id = ((Prop)site).id;
                theSite.Name = ((Prop)site).name;
                theSite.X = site.x;
                theSite.Y = site.y;
                theSite.Fields = new Dictionary<string, string>();
                foreach (var kv in site.fields)
                {
                    theSite.Fields.Add(kv.Key, kv.Value);
                }
                theSite.Type = theSite.Fields.ContainsKey("Standby") ? "standby" : theSite.Fields.ContainsKey("Charge") ? "charge" : theSite.Fields.ContainsKey("Shelf") ? "shelf" : "default";
                map.Sites.Add(theSite);
            }

            map.Tracks = new List<ExpandoObject>();
            map.CircularArcTracks = new List<ExpandoObject>();
            map.BezierTracks = new List<ExpandoObject>();
            var allTracks = SimpleLib.GetAllTracks();
            foreach (var track in allTracks)
            {
                switch (track)
                {
                    case UITrack uiTrack:
                    {
                        dynamic theTrack = new ExpandoObject();
                        theTrack.Id = uiTrack.id;
                        theTrack.A = uiTrack.siteA;
                        theTrack.B = uiTrack.siteB;
                        theTrack.Fields = new Dictionary<string, string>();
                        foreach (KeyValuePair<string, string> kv in uiTrack.fields)
                        {
                            theTrack.Fields.Add(kv.Key, kv.Value);
                        }

                        theTrack.Direction = uiTrack.direction switch
                        {
                            1 => "a2b",
                            2 => "b2a",
                            _ => "both"
                        };
                        theTrack.Type = 0;
                        map.Tracks.Add(theTrack);
                        break;
                    }
                    case UICircularArcTrack circularArcTrack:
                    {
                        dynamic theTrack = new ExpandoObject();
                        theTrack.Id = circularArcTrack.id;
                        theTrack.A = circularArcTrack.siteA;
                        theTrack.B = circularArcTrack.siteB;
                        theTrack.Fields = new Dictionary<string, string>();
                        foreach (var kv in circularArcTrack.fields)
                        {
                            theTrack.Fields.Add(kv.Key, kv.Value);
                        }

                        theTrack.Direction = circularArcTrack.direction switch
                        {
                            1 => "a2b",
                            2 => "b2a",
                            _ => "both"
                        };
                        //添加原点坐标、半径、开始角度、结束角度
                        theTrack.Type = 1;
                        theTrack.CenterX = circularArcTrack.Arc.Center.X;
                        theTrack.CenterY = circularArcTrack.Arc.Center.Y;
                        theTrack.Radius = circularArcTrack.Arc.Radius;
                        theTrack.AngleStart = circularArcTrack.Arc.AngleStart;
                        theTrack.AngleEnd = circularArcTrack.Arc.AngleEnd;
                        //获取圆弧的控制点
                        var controlPoint = ArcHelper.CalculateControlPoint(
                            circularArcTrack.Arc.PointStart.X, circularArcTrack.Arc.PointStart.Y,
                            circularArcTrack.Arc.PointEnd.X, circularArcTrack.Arc.PointEnd.Y,
                            circularArcTrack.Arc.Center.X, circularArcTrack.Arc.Center.Y,
                            circularArcTrack.Arc.Radius,
                            circularArcTrack.Arc.AngleStart, circularArcTrack.Arc.AngleEnd);
                        theTrack.ControlPointsX = controlPoint.X;
                        theTrack.ControlPointsY = controlPoint.Y;
                        map.CircularArcTracks.Add(theTrack);
                        break;
                    }
                    case UIBezierTrack bezierTrack:
                    {
                        dynamic theTrack = new ExpandoObject();
                        theTrack.Id = bezierTrack.id;
                        theTrack.A = bezierTrack.siteA;
                        theTrack.B = bezierTrack.siteB;
                        theTrack.Fields = new Dictionary<string, string>();
                        foreach (var kv in bezierTrack.fields)
                        {
                            theTrack.Fields.Add(kv.Key, kv.Value);
                        }

                        theTrack.Direction = bezierTrack.direction switch
                        {
                            1 => "a2b",
                            2 => "b2a",
                            _ => "both"
                        };
                        //根据typeInfo获取控制点个数
                        theTrack.Type = 2;
                        var array = bezierTrack.typeInfo.Split(',');
                        var num = int.Parse(array[1]);//获取控制点的个数(包括起点和终点)
                        var list = new List<Vector2>();
                        for (var i = 0; i < num; i++)
                        {
                            //只记录中间的控制点
                            if (i <= 0 || i >= num - 1) continue;
                            float x = float.Parse(array[2 + i * 2]);
                            float y = float.Parse(array[3 + i * 2]);
                            list.Add(new Vector2(x, y));
                        }
                        theTrack.controlPoints = list;
                        map.BezierTracks.Add(theTrack);
                        break;
                    }
                    default:
                        break;
                }
            }

            return map;
        }
    }

    public class ArcHelper
    {
        /// <summary>
        /// 获取圆弧控制点
        /// </summary>
        /// <returns></returns>
        public static PointF CalculateControlPoint(float pointStartX, float pointStartY, float pointEndX, float pointEndY, float centerX, float centerY, float radius, float angleStart, float angleEnd)
        {
            PointF center = new PointF(centerX, centerY);
            double startAngle = angleStart * 3.14159 / 180.0;
            double endAngel = angleEnd * 3.14159 / 180.0;
            if (angleStart > angleEnd)//如果起始角度小于结束角度就加上360度
            {
                endAngel += 2 * 3.14159;
            }
            PointF midPoint = new PointF(
            (float)(center.X + radius * Math.Cos((startAngle + endAngel) / 2)),
            (float)(center.Y + radius * Math.Sin((startAngle + endAngel) / 2)));
            return midPoint;
        }
    }

    public class LidarMap
    {
        public string LidarMapsBase64 { get; set; }
        public float DistanceX { get; set; }
        public float DistanceY { get; set; }
        public float Ratio { get; set; }
        private static readonly HttpClient hc = new HttpClient();
        public static async Task<LidarMap> GetLidarMap()
        {
            var par = JsonConvert.DeserializeAnonymousType(await hc.GetStringAsync($"http://127.0.0.1:4321/getMapParameters"),
                new { up = 0f, down = 0f, left = 0f, right = 0f, pt = 0 });
            var lengthWidthRatio =Math.Abs((par.right - par.left) / (par.up - par.down));
            var height = 1024;var width = 1024;
            if (lengthWidthRatio > 1)
            {
                height = (int)(1024 / lengthWidthRatio);
            }
            else
            {
                width = (int)(1024 * lengthWidthRatio);
            }
            var mapBmp= new Bitmap((await hc.GetStreamAsync($"http://127.0.0.1:4321/getMapPng?width={width}&height={height}")));
            for(int x =0;x<mapBmp.Width;x++)
            {
                for (int y = 0; y < mapBmp.Height; y++)
                {
                    Color pixColor = mapBmp.GetPixel(x, y);
                    if (pixColor.R != 255 || pixColor.G != 255 || pixColor.B != 255)
                    {
                        mapBmp.SetPixel(x, y, Color.FromArgb(0,pixColor));
                    }
                    else
                    {
                        mapBmp.SetPixel(x,y,Color.Black);
                    }
                }
            }
            return new LidarMap
            {
                LidarMapsBase64 = "data:image/png;base64," + BitmapToBase64(mapBmp, ImageFormat.Png),
                DistanceX = par.left,
                DistanceY = par.up,
                Ratio = lengthWidthRatio > 1?Math.Abs(par.left-par.right)/1024: Math.Abs(par.up - par.down)/1024,
            };
        }

        static string BitmapToBase64(Bitmap bmp, ImageFormat format)
        {
            using MemoryStream ms = new MemoryStream();
            bmp.Save(ms, format); // 保存格式可以是Png, Jpeg等
            byte[] imageBytes = ms.ToArray();
            string base64String = Convert.ToBase64String(imageBytes);
            return base64String;
        }
    }
}
