using System;
using System.Collections.Generic;
using System.Windows.Media;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Ink;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;

namespace WpfApp1.Structure
{
    internal class Edge : Symbol
    {
        public double weight;
        public List<Node> nodes_from;
        public List<Node> nodes_to;

        public Edge(int id, string text, string category, string color, double[] center, StrokeCollection strokes, List<Symbol> inclusions, Canvas video_text) : base(id, text, category, color, center, strokes, inclusions, video_text)
        {
            this.weight = 1;
            this.nodes_from = new List<Node>();
            this.nodes_to = new List<Node>();
            //this.text_box.Visibility = Visibility.Collapsed;
            ResetArrow();
        }

        public Edge(int id, Canvas video_text) : base(id, video_text)
        {
            this.weight = 1;
            this.nodes_from = new List<Node>();
            this.nodes_to = new List<Node>();
            //this.text_box.Visibility = Visibility.Collapsed;
        }

        public override string ToString()
        {
            return id.ToString() + ": " + text;
        }

        public override void SetText(string text)
        {
            this.text = text;
        }

        public override void SetCategory(string category)
        {
            if (this.category == category)
            {
                return;
            }
            this.category = category;
            ResetArrow();
        }

        public override void SetStrokes(StrokeCollection strokes)
        {
            this.strokes = strokes.Clone();
            Resized();
        }

        public void SetWeight(double weight)
        {
            this.weight = weight;
        }

        public void Reverse()
        {
            if (category != "Arrow")
            {
                return;
            }
        }

        public override void RefreshTextBoxPos()
        {
            double x1 = strokes[0].StylusPoints[0].X, y1 = strokes[0].StylusPoints[0].Y;
            double x2 = strokes[0].StylusPoints[1].X, y2 = strokes[0].StylusPoints[1].Y;
            double dx = x2 - x1, dy = y2 - y1;
            double ofs = 10;
            //Canvas.SetTop(text_box, dy >= 0 ? y1 + ofs : y1 - ofs - text_box.ActualHeight);
            //Canvas.SetLeft(text_box, dx >= 0 ? x1 + ofs : x1 - ofs - text_box.ActualWidth);
            Canvas.SetTop(text_thumb, dy >= 0 ? y1 + ofs : y1 - ofs - text_thumb.ActualHeight);
            Canvas.SetLeft(text_thumb, dx >= 0 ? x1 + ofs : x1 - ofs - text_thumb.ActualWidth);
            if (id == 202)
            {
                Canvas.SetTop(text_thumb, dy >= 0 ? y1 + ofs + 15 : y1 - ofs - text_thumb.ActualHeight + 15);
                Canvas.SetLeft(text_thumb, dx >= 0 ? x1 + ofs - 15 : x1 - ofs - text_thumb.ActualWidth - 15);
            }
            if (id == 200)
            {
                Canvas.SetTop(text_thumb, dy >= 0 ? y1 + ofs : y1 - ofs - text_thumb.ActualHeight);
                Canvas.SetLeft(text_thumb, dx >= 0 ? x1 + ofs + 60 : x1 - ofs - text_thumb.ActualWidth + 60);
            }
        }

        public override void RefreshTextBox()
        {
            Rect boundingBox;
            if (strokes.Count > 0)
            {
                boundingBox = strokes.GetBounds();
                double x1 = strokes[0].StylusPoints[0].X, y1 = strokes[0].StylusPoints[0].Y;
                double x2 = strokes[0].StylusPoints[1].X, y2 = strokes[0].StylusPoints[1].Y;
                double dx = x2 - x1, dy = y2 - y1;
                if (dx >= dy && dx * dy >= 0 || dx >= -dy && dx * dy <= 0)
                {
                    text_thumb.MaxWidth = Math.Max(170, boundingBox.Right - x1);
                }
                else
                {
                    text_thumb.MaxWidth = Math.Max(170, x1 - boundingBox.Left);
                }
            }
            else
            {
                text_thumb.MaxWidth = 70;
            }
            RefreshTextBoxPos();
        }

        public void ResetArrow()
        {
            if (category != "Arrow" || strokes.Count == 0)
            {
                return;
            }
            int count = strokes[0].StylusPoints.Count;
            double DirectX = strokes[0].StylusPoints[count - 1].X - strokes[0].StylusPoints[count - 2].X;
            double DirectY = strokes[0].StylusPoints[count - 1].Y - strokes[0].StylusPoints[count - 2].Y;
            double norm = Math.Sqrt(Math.Pow(DirectX, 2) + Math.Pow(DirectY, 2));
            double k = 16 / norm;
            double x = strokes[0].StylusPoints[count - 1].X - k * DirectX;
            double y = strokes[0].StylusPoints[count - 1].Y - k * DirectY;
            double x1 = x + 5 * DirectY / norm, y1 = y - 5 * DirectX / norm;
            double x2 = x - 5 * DirectY / norm, y2 = y + 5 * DirectX / norm;
            StylusPointCollection stylusPoints1 = new StylusPointCollection
            {
                strokes[0].StylusPoints[count - 1],
                new StylusPoint(x1, y1)
            };
            StylusPointCollection stylusPoints2 = new StylusPointCollection
            {
                strokes[0].StylusPoints[count - 1],
                new StylusPoint(x2, y2)
            };
            switch (strokes.Count)
            {
                case 1:
                    strokes.Add(new Stroke(stylusPoints1, strokes[0].DrawingAttributes));
                    strokes.Add(new Stroke(stylusPoints2, strokes[0].DrawingAttributes));
                    break;
                case 3:
                    strokes[1].StylusPoints = stylusPoints1;
                    strokes[2].StylusPoints = stylusPoints2;
                    break;
                default:
                    throw new Exception("error strokes count");
            }
        }

        public override Edge Clone()
        {
            Edge edge = new Edge(id, text, category, color, center, strokes, inclusions, text_thumb.Parent as Canvas);
            edge.weight = weight;
            edge.text_thumb.Visibility = Visibility.Hidden;
            return edge;
        }

        public override void Disconnect()
        {
            foreach (Node node in this.nodes_from)
            {
                node.edges_out.Remove(this);
            }
            foreach (Node node in this.nodes_to)
            {
                node.edges_in.Remove(this);
            }
            foreach (Content content in this.inclusions)
            {
                content.groups.Remove(this);
            }
            //base.Disconnect();
        }
        public override void Connect()
        {
            foreach (Node node in this.nodes_from)
            {
                node.edges_out.Add(this);
            }
            foreach (Node node in this.nodes_to)
            {
                node.edges_in.Add(this);
            }
            foreach (Content content in this.inclusions)
            {
                content.groups.Add(this);
            }
            //base.Connect();
        }
    }
}
