using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace HistoryDLL
{
    /// <summary>
    /// HomePage.xaml 的互動邏輯
    /// </summary>
    public partial class HomePage : UserControl
    {
        public event EventHandler OnLoadProgessComplete;

        DispatcherTimer dt = new DispatcherTimer();

        Storyboard progressWidthStoryBoard = new Storyboard();
        Storyboard progressHeightStoryBoard = new Storyboard();
        DoubleAnimation dbOffsetWidth;
        DoubleAnimation dbOffsetHeight;

        //亂數飛入
        private Random rnd = new Random(Guid.NewGuid().GetHashCode());
        //Block size
        private int blockWidth = 0;
        private int blockHeight = 0;
        private int nonesize = 0;
        //事件數量
        private int eventTotalCount = 0;
        //載入完成數量
        private int eventLoadCount = 0;
        //歷史牆控制項
        private Grid HistoryWallControl = new Grid();
        //區塊大小設定
        private static int cutForTwowidth = 289;
        private static int cutForTwoheight = 224;
        private static int cutForSixwidth = 209;
        private static int cutForSixheight = 157;
        //紀錄顯示畫面的年份
        public List<XmlData> xmlDataList = new List<XmlData>();
        public List<Border> borderlist = new List<Border>();
        public List<MyBorder> myborderList = new List<MyBorder>();
        public int StoryBoardTime = 200;
        public int DelayTimeRate = 100;
        public int HistoryWallTime = 600;
        SolidColorBrush sb = new SolidColorBrush(ConfigSettingClass.TimelineCollect.BackgroundColor);
        private SolidColorBrush TextBlockExtendColor = new SolidColorBrush(ConfigSettingClass.TimelineCollect.TextColor);

        public HomePage(int width, int height)
        {
            InitializeComponent();

            this.uxLoadBar.Width = width;
            this.uxLoadBar.Height = height;

            if (GlobalFunction.isSolutionUsing4K)
            {
                cutForTwowidth *= 2;
                cutForTwoheight *= 2;
                cutForSixwidth *= 2;
                cutForSixheight *= 2;

                uxProgressBar.Height *= 2;
                uxProgressBar.Margin = new Thickness(0, uxProgressBar.Margin.Top * 2, 0, 0);
            }

            SetStoryboardMotionX();
            SetStoryboardMotionY();

            uxProgressBar.Background = sb;
            uxLoadingProgress.LoadingCompleted += new EventHandler(uxLoadingProgress_LoadingCompleted);
            uxLoadingProgress.Start();
            uxLoadingProgress.Minimum = 0;
            uxLoadingProgress.Maximum = 100;
        }

        private void uxLoadingProgress_LoadingCompleted(object sender, EventArgs e)
        {
            progressWidthStoryBoard.Stop();

            dbOffsetWidth.From = this.uxProgressBar.Width;
            dbOffsetWidth.To = (eventLoadCount * this.uxLoadBar.Width) / eventTotalCount;
            progressWidthStoryBoard.Begin();
            uxLoadingProgress.Visibility = System.Windows.Visibility.Collapsed;

            CloseLoadingMap();

            OnLoadProgessComplete?.Invoke(this,null);
        }

        private void CloseLoadingMap()
        {
            for (int i = 0; i < 60; i++)
            {
                Path path = new Path();

                path = FindName("m" + string.Format("{0:D2}", i)) as Path;
                path.Visibility = System.Windows.Visibility.Collapsed;
            }
            Grid gd = new Grid();

            gd = FindName("m60") as Grid;
            gd.Visibility = System.Windows.Visibility.Collapsed;
        }

        public void SetBlockCommonSetting(int width, int height, int nousesize)
        {
            blockWidth = width;
            blockHeight = height;
            nonesize = nousesize;

            if (GlobalFunction.isSolutionUsing4K)
            {
                //blockWidth *= 2;
                //blockHeight *= 2;
                //nonesize *= 2;
            }
        }

        private void HistoryWallStart()
        {
            dt.Interval = TimeSpan.FromMilliseconds(HistoryWallTime);
            dt.Tick += new EventHandler(dt_Tick);
            dt.Start();
        }

        void dt_Tick(object sender, EventArgs e)
        {
            dt.Stop();
            //將歷史牆提到最上層
            Canvas.SetZIndex(HistoryWallControl, 1);
            OpacityFadeInAndOut();
        }

        //設定時間讓歷史牆的Opacity漸改變
        private void OpacityFadeInAndOut()
        {
            Storyboard historywallshow = new Storyboard();

            DoubleAnimation dbOffset = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(200),
                EasingFunction = new ExponentialEase()
                {
                    EasingMode = EasingMode.EaseIn,
                    Exponent = 3,
                },
                From = 0,
                To = 1
            };

            Storyboard.SetTarget(dbOffset, HistoryWallControl);
            Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.OpacityProperty));

            historywallshow.Completed += new EventHandler(historywallshow_Completed);
            historywallshow.Children.Add(dbOffset);
            historywallshow.FillBehavior = FillBehavior.HoldEnd;
            historywallshow.Begin();
        }

        void historywallshow_Completed(object sender, EventArgs e)
        {
            HistoryWallControl.Opacity = 1;
            //結束後~將歷史牆降到最下層~不然點擊會點不到
            Canvas.SetZIndex(HistoryWallControl, 0);
            uxLoadBar.Opacity = 0;
            ReleaseAllSetting();
        }

        //釋放所有資源
        private void ReleaseAllSetting()
        {
            xmlDataList = new List<XmlData>();
            borderlist = new List<Border>();
            myborderList = new List<MyBorder>();
            progressWidthStoryBoard = new Storyboard();
            progressHeightStoryBoard = new Storyboard();
            uxLoadBar.Visibility = System.Windows.Visibility.Collapsed;
        }

        //將每個年分區塊顯示出來~並且播放飛入的動畫
        private void ShowBlock()
        {
            uxProgressBar.Opacity = 0;
            uxGradientStop.Offset = 1;

            for (int i = 0; i < borderlist.Count; i++)
            {
                uxLoadBar.Children.Add(borderlist[i]);
            }

            this.Refresh();
            for (int i = 0; i < myborderList.Count; i++)
            {
                uxLoadBar.Children.Add(myborderList[i]);
                myborderList[i].FlyAnimationStart();
                this.Refresh();
            }
        }

        /// <summary>
        /// 設定每個Block的位置
        /// </summary>
        private void SetBlockPos()
        {
            int marginbtm = 250;

            if (GlobalFunction.isSolutionUsing4K)
                marginbtm *= 2;

            //設定每個年分區塊的位置
            for (int count = 0; count < borderlist.Count; count++)
            {
                //先設定第一個
                if (count == 0)
                {
                    borderlist[count].Margin = new Thickness(-nonesize, 0, 0, marginbtm);
                    continue;
                }
                borderlist[count].Margin = new Thickness(borderlist[count - 1].Margin.Left + blockWidth, 0, 0, marginbtm);
            }
        }

        /// <summary>
        /// 根據事件的數量~新建出Image並設定其動畫
        /// </summary>
        private void SetEventAnimation()
        {
            int eventcount = xmlDataList.Count;

            for (int index = 0; index < eventcount; index++)
            {
                //如果該年只有兩個事件~的動畫位置
                if (xmlDataList[index].monthclassList.Count <= 2)
                {
                    for (int i = 0; i < xmlDataList[index].monthclassList.Count; i++)
                    {
                        int randonvalue = rnd.Next(0, 401);

                        if (i == 0)
                        {
                            int fitValue = 92;

                            if (GlobalFunction.isSolutionUsing4K)
                                fitValue *= 2;
                            //區塊寬度, 區塊高度, 該區塊的起始位置 (左 + 底), 該區塊飛入後的終點位置 (左 + 底) + 動畫時間, 動畫的延遲時間
                            //91 : 77 (年份寬度) + "上下"區塊間的Thickness寬度 10 + 切割該區塊的係數 4
                            MyBorder newimage = new MyBorder(cutForTwowidth, cutForTwoheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - cutForTwowidth) / 2, borderlist[index].Margin.Bottom + fitValue, StoryBoardTime, randonvalue);

                            myborderList.Add(newimage);
                        }
                        else
                        {
                            int fitValue = 103;

                            if (GlobalFunction.isSolutionUsing4K)
                                fitValue *= 2;

                            //97 : 77 (年份寬度) + "上下"區塊間的Thickness寬度 10 + 切割下區塊的係數 (上下) 4 + 往上多飛一個Thickness寬度 5 + 切割該區塊的係數(下) 2
                            MyBorder newimage = new MyBorder(cutForTwowidth, cutForTwoheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - cutForTwowidth) / 2, borderlist[index].Margin.Bottom + fitValue + (i * cutForTwoheight), StoryBoardTime, randonvalue);

                            myborderList.Add(newimage);
                        }
                    }
                }
                //如果該年超過兩個事件~則動畫位置
                else
                {
                    for (int i = 0; i < xmlDataList[index].monthclassList.Count; i++)
                    {
                        int randonvalue = rnd.Next(0, 401);
                        if (i > 5)
                        {
                            break;
                        }
                        //排(橫)
                        int Row = i / 2;
                        //列(直)
                        int colu = i % 2;

                        int thicknessValue = 5;
                        int fitXvalue = 210;
                        int fitYvalue = 91;

                        if (GlobalFunction.isSolutionUsing4K)
                        {
                            thicknessValue *= 2;
                            fitXvalue *= 2;
                            fitYvalue *= 2;
                        }

                        if (Row == 0)
                        {
                            if (colu == 0)
                            {
                                MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2, borderlist[index].Margin.Bottom + fitYvalue, StoryBoardTime, randonvalue);
                                myborderList.Add(newimage);
                            }
                            else
                            {
                                //225 : cutForSixwidth 210 + 該區塊的"左右"的Thickness 10 + 右邊區塊的"左"Thickness 5
                                MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2 + ((fitXvalue + thicknessValue * 2)), borderlist[index].Margin.Bottom + fitYvalue, StoryBoardTime, randonvalue);
                                myborderList.Add(newimage);
                            }
                        }
                        else
                        {
                            if (colu == 0)
                            {
                                //14 : 區塊"上下"的Thickness 10 + 切割該區塊的係數 4
                                MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2, borderlist[index].Margin.Bottom + fitYvalue + (Row * cutForSixheight) + (11 * Row), StoryBoardTime, randonvalue);
                                myborderList.Add(newimage);
                            }
                            else
                            {
                                //225 : cutForSixwidth 210 + 該區塊的"左右"的Thickness 10 + 右邊區塊的"左"Thickness 5
                                MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2 + (fitXvalue + thicknessValue * 2), borderlist[index].Margin.Bottom + fitYvalue + (Row * cutForSixheight) + (11 * Row), StoryBoardTime, randonvalue);
                                myborderList.Add(newimage);
                            }
                        }
                    }
                }
            }
        }

        #region X 與 Y 軸動畫
        private void SetStoryboardMotionX()
        {
            progressWidthStoryBoard = new Storyboard();

            dbOffsetWidth = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(1000),
                EasingFunction = new ExponentialEase()
                {
                    EasingMode = EasingMode.EaseIn,
                    Exponent = 0.3
                },
            };

            Storyboard.SetTarget(dbOffsetWidth, this.uxProgressBar);
            Storyboard.SetTargetProperty(dbOffsetWidth, new PropertyPath(Grid.WidthProperty));
            progressWidthStoryBoard.Children.Add(dbOffsetWidth);
            progressWidthStoryBoard.Completed += new EventHandler(progressStoryBoard_Completed);
            progressWidthStoryBoard.FillBehavior = FillBehavior.HoldEnd;
        }

        void progressStoryBoard_Completed(object sender, EventArgs e)
        {
            progressHeightStoryBoard.Begin();
        }

        public void SetEventCount(int count)
        {
            eventTotalCount = count;
        }

        private void SetStoryboardMotionY()
        {
            progressHeightStoryBoard = new Storyboard();
            int aniHeight = 77;

            if (GlobalFunction.isSolutionUsing4K)
                aniHeight *= 2;

            dbOffsetHeight = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(500),
                EasingFunction = new ExponentialEase()
                {
                    EasingMode = EasingMode.EaseIn,
                    Exponent = 0.3
                },
                From = this.uxProgressBar.Height,
                To = aniHeight,
            };

            Storyboard.SetTarget(dbOffsetHeight, this.uxProgressBar);
            Storyboard.SetTargetProperty(dbOffsetHeight, new PropertyPath(Grid.HeightProperty));
            progressHeightStoryBoard.Children.Add(dbOffsetHeight);
            progressHeightStoryBoard.Completed += new EventHandler(progressHeightStoryBoard_Completed);
            progressHeightStoryBoard.FillBehavior = FillBehavior.HoldEnd;
        }

        void progressHeightStoryBoard_Completed(object sender, EventArgs e)
        {
            while (true)
            {
                if (xmlDataList.Count > 0)
                {
                    for (int i = 0; i < xmlDataList.Count; i++)
                    {
                        Border bd = new Border();
                        TextBlock tb = new TextBlock();

                        tb.Foreground = TextBlockExtendColor;
                        tb.FontSize = GlobalFunction.isSolutionUsing4K ? 40 * 1.5 : 40;
                        tb.TextTrimming = TextTrimming.CharacterEllipsis;
                        tb.VerticalAlignment = System.Windows.VerticalAlignment.Center;
                        tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
                        string langStr = xmlDataList[i].yearlan1;

                        if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 1)
                        {
                            langStr = xmlDataList[i].yearlan2;
                        }
                        else if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 2)
                        {
                            langStr = xmlDataList[i].yearlan3;
                        }
                        else if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 3)
                        {
                            langStr = xmlDataList[i].yearlan4;
                        }
                        tb.Text = langStr;

                        bd.Child = tb;
                        bd.Width = blockWidth;
                        bd.Height = blockHeight;
                        bd.BorderThickness = new Thickness(5);
                        bd.BorderBrush = Brushes.Transparent;
                        bd.Background = sb;
                        bd.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                        bd.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;

                        borderlist.Add(bd);
                    }
                    break;
                }
            }
            //在整個動畫結束後~代表資料已經載入完成此時才知道顯示在前面個年份是哪幾個~
            //設定每個Block的位置
            SetBlockPos();
            //根據事件的數量~新建出Image並設定其動畫
            SetEventAnimation();
            //顯示區塊及動畫
            ShowBlock();
            //設定時間歷史牆啟動
            HistoryWallStart();
        }

        #endregion

        //觸發整個動畫起始位置
        public void AddLoadCount()
        {
            eventLoadCount++;

            RunProgressStoryboard();
        }

        private void RunProgressStoryboard()
        {
            uxLoadingProgress.EndValue = ((double)eventLoadCount / (double)eventTotalCount) * 100d;
        }

        internal void SetHistoryWallControl(Grid uxCyclicGrid)
        {
            HistoryWallControl = uxCyclicGrid;
        }
    }

    /// <summary>擴充uiElement類別的方法</summary>
    /// <remarks>為uiElement類別增加element即時重整的功能</remarks>
    public static class uiElementExtension
    {
        private static Action NoDoDelegate = delegate () { };

        public static void Refresh(this UIElement uiElement)
        {
            uiElement.Dispatcher.Invoke(DispatcherPriority.Render, NoDoDelegate);
        }

        public static void WebRefresh(this UIElement uiElement)
        {
            uiElement.Dispatcher.Invoke(DispatcherPriority.ContextIdle, NoDoDelegate);
        }
    }

    //自訂義Image
    public class MyBorder : Border
    {
        //區塊大小
        public int borderwidth;
        public int borderheight;
        //動畫起始位置
        public double beginPosX;
        public double beginPosY;
        //動畫結束位置
        public double endPosX;
        public double endPosY;

        public Storyboard myborderStoryboard = new Storyboard();
        //動畫運行時間
        public int storyboardTime;
        //動畫的Delay time 讓整個飛入的物件不會同時飛
        public int storyboardBeginTime;
        private SolidColorBrush RotateContainColor = new SolidColorBrush(ConfigSettingClass.EventCollect.BackgroundColor);

        public MyBorder(int width, int height, double bPosX, double bPosY, double ePosX, double ePosY, int StoryboardTime, int STbeginTime)
        {
            borderwidth = width;
            borderheight = height;
            beginPosX = bPosX;
            beginPosY = bPosY;
            endPosX = ePosX;
            endPosY = ePosY;
            storyboardTime = StoryboardTime;
            storyboardBeginTime = STbeginTime;

            this.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            this.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
            this.Background = RotateContainColor;
            this.BorderThickness = new Thickness(0);
            this.Opacity = 0;

            SetTheFlyStoryboard();
        }

        public void FlyAnimationStart()
        {
            this.Opacity = 1;
            myborderStoryboard.Begin();
        }

        //飛入的動畫
        private void SetTheFlyStoryboard()
        {
            ThicknessAnimation dbOffset = new ThicknessAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(storyboardTime),
                EasingFunction = new CircleEase()
                {
                    EasingMode = EasingMode.EaseOut,
                },
                From = new Thickness(beginPosX, 0, 0, beginPosY),
                To = new Thickness(endPosX, 0, 0, endPosY)
            };

            DoubleAnimation dbOffsetWidth = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(storyboardTime),
                EasingFunction = new CircleEase()
                {
                    EasingMode = EasingMode.EaseOut,
                },
                From = 0,
                To = borderwidth
            };

            DoubleAnimation dbOffsetHeight = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(storyboardTime),
                EasingFunction = new CircleEase()
                {
                    EasingMode = EasingMode.EaseOut,
                },
                From = 0,
                To = borderheight
            };

            DoubleAnimation dbOffsetOpacity = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(storyboardTime),
                EasingFunction = new CircleEase()
                {
                    EasingMode = EasingMode.EaseOut,
                },
                From = 0,
                To = 1
            };

            Storyboard.SetTarget(dbOffset, this);
            Storyboard.SetTarget(dbOffsetWidth, this);
            Storyboard.SetTarget(dbOffsetHeight, this);
            Storyboard.SetTarget(dbOffsetOpacity, this);
            Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Border.MarginProperty));
            Storyboard.SetTargetProperty(dbOffsetWidth, new PropertyPath(Border.WidthProperty));
            Storyboard.SetTargetProperty(dbOffsetHeight, new PropertyPath(Border.HeightProperty));
            Storyboard.SetTargetProperty(dbOffsetOpacity, new PropertyPath(Border.OpacityProperty));

            myborderStoryboard.BeginTime = TimeSpan.FromMilliseconds(storyboardBeginTime);
            myborderStoryboard.Children.Add(dbOffset);
            myborderStoryboard.Children.Add(dbOffsetWidth);
            myborderStoryboard.Children.Add(dbOffsetHeight);
            myborderStoryboard.Children.Add(dbOffsetOpacity);
            myborderStoryboard.FillBehavior = FillBehavior.HoldEnd;
        }
    }
}
