using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using ChaKi.Entity.Corpora;
using ChaKi.Entity.Corpora.Annotations;
using ChaKi.Common;
using ChaKi.Common.Settings;
using ChaKi.Entity.Settings;

namespace DependencyEditSLA.Widgets
{
    class DepArrowArc : DepArrow
    {
        public DepArrowArc(Link _link, int _id, int _from, int _to, Rectangle _fromBox, Rectangle _toBox)
            : base(_link, _id, _from, _to, _fromBox, _toBox)
        {
        }

        public override void RecalcLayout(Rectangle fromBox, Rectangle toBox)
        {
            m_FromBox = fromBox;
            m_ToBox = toBox;
            this.StartPnt = new Point((fromBox.Right + fromBox.Left) / 2, fromBox.Bottom);
            this.EndPnt = new Point(toBox.Left, toBox.Bottom);
            this.EndPnt2 = new Point(toBox.Right, toBox.Bottom);
        }

        public override void Draw(Graphics g, bool bDraft, Point offset)
        {
            if (!this.Visible)
            {
                return;
            }

            Pen srcPen = LinkPens.Find(this.Tag);
            Pen pen = (Pen)srcPen.Clone();
            if (IsSelected) pen.Color = Color.Red;
            if (IsCrossing) pen.Color = Color.DarkOrange;
            if (this.Tag == "P")
            {   // "P"はNon-directedなのでLinecapなし. TODO: 名称ではなくIsDirectedによる判定が必要
                pen.SetLineCap(LineCap.Square, LineCap.Square, DashCap.Flat);
            }

            DrawParamsArc dp = new DrawParamsArc(this.StartPnt, this.EndPnt, this.EndPnt2, bDraft, offset);

            // HitTest領域を求めて保存しておく
            if (true/*typeid(*pDC) != typeid(CMetaFileDC)*/)
            {
                GraphicsPath gp = new GraphicsPath();
                gp.AddBezier(dp.ps, dp.ps1, dp.pe1, dp.pe);
                gp.Widen(m_RegionPen);

                if (m_Region != null)
                {
                    m_Region.Dispose();
                    m_Region = new Region(gp);
                }
            }
            //本来の描画処理
            if (!DepEditSettings.Current.ReverseDepArrowDirection)
            {
                g.DrawBezier(pen, dp.ps, dp.ps1, dp.pe1, dp.pe);
            }
            else
            {
                g.DrawBezier(pen, dp.pe, dp.pe1, dp.ps1, dp.ps);
            }

            // タグラベルの更新処理
            if (!bDraft)
            {
                RectangleF r = m_Region.GetBounds(g);
                this.TagLabel.Location = new Point((int)(r.Left+r.Right)/2, (int)r.Bottom-5);
                this.TagLabel.Text = this.Tag;
            }
            pen.Dispose();
        }
    }


    class DrawParamsArc
    {
        public DrawParamsArc(Point _s, Point _e, Point _e2, bool bDraft, Point offset)
        {
            double curveParamX = DepEditSettings.Current.CurveParamX;
            double curveParamY = DepEditSettings.Current.CurveParamY;

            isReverse = (_s.X > _e.X);
            ps = new Point(_s.X, _s.Y);
            if (!bDraft)
            {
                if (!isReverse)
                {
                    pe = new Point(_e.X + 8, _e.Y);
                }
                else
                {
                    pe = new Point(_e2.X - 20, _e2.Y);
                }
            }
            else
            {
                pe = new Point(_e.X, _e.Y);
            }
            int w = pe.X - ps.X;
            ps1 = new Point((int)(ps.X + w * curveParamX), (int)(ps.Y + Math.Abs(w) * curveParamY));
            pe1 = new Point((int)(pe.X - w * curveParamX), (int)(pe.Y + Math.Abs(w) * curveParamY));
            pm = new Point((ps1.X + pe1.X) / 2, (ps1.Y + pe1.Y) / 2);

            tagLocation = new Point(pm.X + 5, (int)(ps.Y + Math.Abs(w) * curveParamY * 0.9));

            ps.Offset(offset);
            pe.Offset(offset);
            ps1.Offset(offset);
            pe1.Offset(offset);
            pm.Offset(offset);
            tagLocation.Offset(offset);
        }

        public Point ps;
        public Point pe;
        public Point ps1;
        public Point pe1;
        public Point pm;
        public Point tagLocation;
        public bool isReverse;
    }
}
