using Microsoft.WindowsAPICodePack.Shell;
using System;
using System.Collections.Generic;
using System.IO;
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>
    /// PlaneRotateMap.xaml 的互動邏輯
    /// </summary>
    public partial class PlaneRotateMap : UserControl
    {
        //創造 PlaneRotateMap 物件
        private delegate void CreatePlaneRotateMapDelegate();
        private delegate void DynamicChangeLan();

        private DispatcherTimer RotateWaitTime = new DispatcherTimer();
        //該PlaneRotate中有幾個可以顯示的物件
        private int ImageWidth, ImageHeight;
        private List<FrameworkElement> ElementForRotateList = new List<FrameworkElement>();
        private Rectangle RectForTouch = new Rectangle();
        //當前顯示的物件是屬於ElementForRotateList中的第幾個索引
        private int CurrentShowIndex = 0;
        //該輪播塊是屬於該年事件中的第幾個索引
        public int indexOfEvent = -1;
        //亂數產生
        private Random rnd = new Random(Guid.NewGuid().GetHashCode());
        //切換資訊的亂數時間範圍 changeInfoTimeMin <= s < changeInfoTimeMax
        private int changeInfoTimeMin = 8;
        private int changeInfoTimeMax = 32;
        //Other Number
        private double RotateAngle = 10.0;   //區塊旋轉時候的角度
        private double TextFontSize = 23;                  //顯示的資訊如果是文字~則設定文字大小
        private int RotateAnimationTime = 400;
        private Storyboard sbStepOne = new Storyboard();
        private DoubleAnimation dbOffsetOne = new DoubleAnimation();
        private Storyboard sbStepTwo = new Storyboard();
        private DoubleAnimation dbOffsetTwo = new DoubleAnimation();

        private SolidColorBrush RotateContainColor = new SolidColorBrush(ConfigSettingClass.EventCollect.BackgroundColor);
        private SolidColorBrush RotateContainTextColor = new SolidColorBrush(ConfigSettingClass.EventCollect.TextColor);
        //判斷是否資料已經到底的紀錄的 Index
        private int RecordInfoCount = 1;
        //資料暫存
        public MonthClass RotateMonthClass = new MonthClass();
        private string[] imgfilter = { ".jpeg", ".jpg", ".bmp", ".png" };
        private string[] mediafilter = { ".mp4", ".wmv", ".mpeg", "mpg", "avi" };

        //該PlaneRotateMap在LiveContainer 中的哪個區塊
        public int BlockIndex = -1;
        public bool ChangeInfo = false;

        public PlaneRotateMap()
        { InitializeComponent(); }

        public PlaneRotateMap(MonthClass sourcemonthClass, int ImageWidth, int ImageHeight)
        {
            InitializeComponent();

            if (GlobalFunction.isSolutionUsing4K)
                TextFontSize *= 1.5;

            //將暫時設定一下顏色
            uxRotateContain.Background = RotateContainColor;
            //設定翻轉頻率
            SetRotateFreq();
            //設定旋轉動作的相關Timer
            SettingRotateMap();
            RotateWaitTime.Tick += new EventHandler(RotateWaitTime_Tick);
            //資料存到緩衝
            RotateMonthClass = sourcemonthClass;
            //設定寬高
            uxRotateContain.Width = uxRotateMainGrid.Width = this.ImageWidth = ImageWidth;
            uxRotateContain.Height = uxRotateMainGrid.Height = this.ImageHeight = ImageHeight;
            //設定可觸控層
            SetTouchLay(ImageWidth, ImageHeight);
            //翻轉角度設定
            uxMyPlanerator.FieldOfView = RotateAngle;
        }

        private void DynamicChangeLanEvent()
        {
            //第 0 個一定是文字
            Grid gd = ElementForRotateList[0] as Grid;
            TextBlock tb = gd.Children[0] as TextBlock;

            //假如現在是第一種語系
            if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language1")
            {
                tb.Text = RotateMonthClass.titleLan1;
            }
            else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language2")
            {
                tb.Text = RotateMonthClass.titleLan2;
            }
            else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language3")
            {
                tb.Text = RotateMonthClass.titleLan3;
            }
            else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language4")
            {
                tb.Text = RotateMonthClass.titleLan4;
            }
        }

        //動態改變 PlaneRotate 內容物件的語系
        internal void ChangeLanByDynamic()
        {
            this.Dispatcher.BeginInvoke(new DynamicChangeLan(DynamicChangeLanEvent),
                        DispatcherPriority.Background);
        }

        private void SetRotateFreq()
        {
            changeInfoTimeMin = 8;

            if (ConfigSettingClass.MainBackCollect.ScreenSetting == 1)
            {
                changeInfoTimeMax = 32;
            }
            else if (ConfigSettingClass.MainBackCollect.ScreenSetting == 2)
            {
                changeInfoTimeMax = 48;
            }
            else if (ConfigSettingClass.MainBackCollect.ScreenSetting == 3)
            {
                changeInfoTimeMax = 64;
            }
        }

        internal void CreatePlaneRotateMap()
        {
            //透過RotateMonthClass取得該PlaneRotateMap 顯示資訊
            GetInformationToShow();
        }

        private void GetInformationToShow()
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new CreatePlaneRotateMapDelegate(AddRotateInfoToList), DispatcherPriority.Background);
            //點擊區
            uxRotateMainGrid.Children.Add(RectForTouch);
        }

        private void SettingRotateMap()
        {
            dbOffsetOne = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(RotateAnimationTime),
                EasingFunction = new PowerEase()
                {
                    EasingMode = EasingMode.EaseIn,
                    Power = 2
                },
            };
            dbOffsetOne.From = 0;
            dbOffsetOne.To = 90;

            dbOffsetTwo = new DoubleAnimation()
            {
                Duration = TimeSpan.FromMilliseconds(RotateAnimationTime),
                EasingFunction = new PowerEase()
                {
                    EasingMode = EasingMode.EaseOut,
                    Power = 2
                },
            };
            dbOffsetTwo.From = -90;
            dbOffsetTwo.To = 0;

            Storyboard.SetTarget(dbOffsetOne, (DependencyObject)this.FindName("uxMyPlanerator"));
            Storyboard.SetTargetProperty(dbOffsetOne, new PropertyPath(NLPlaneRotator.PlaneRotator.RotationXProperty));
            sbStepOne.Children.Add(dbOffsetOne);
            sbStepOne.FillBehavior = FillBehavior.HoldEnd;
            sbStepOne.Completed += new EventHandler(sbStepOne_Completed);

            Storyboard.SetTarget(dbOffsetTwo, (DependencyObject)this.FindName("uxMyPlanerator"));
            Storyboard.SetTargetProperty(dbOffsetTwo, new PropertyPath(NLPlaneRotator.PlaneRotator.RotationXProperty));
            sbStepTwo.Children.Add(dbOffsetTwo);
            sbStepTwo.FillBehavior = FillBehavior.HoldEnd;
        }

        /// <summary>
        /// 旋轉
        /// </summary>
        public void RotateTheObject()
        {
            sbStepOne.Begin();
        }

        public void sbStepOne_Completed(object sender, EventArgs e)
        {
            //改變資料
            if (ChangeInfo)
            {
                SendChangeBlockIndex("Prepare", BlockIndex);
            }
            CurrentShowIndex++;

            ChangeElementForShow(ref CurrentShowIndex);
            sbStepTwo.Begin();
        }

        /// <summary>
        /// 判斷該資料是否已經到底了~如果是~則通知 LiveContainer
        /// </summary>
        /// <param name="RecordInfoCount">紀錄已經播放幾筆資料</param>
        private void CheckTheFileEndToSend(ref int RecordInfoCount)
        {
            if (RecordInfoCount >= ElementForRotateList.Count)
            {
                //到底~將該區塊的索引值傳回 LiveContainer
                SendChangeBlockIndex("DataEnd", BlockIndex);
            }
        }

        /// <summary>
        /// 設定可觸控層以方便之後能夠點擊觸發
        /// </summary>
        private void SetTouchLay(int ImageWidth, int ImageHeight)
        {
            RectForTouch.Width = ImageWidth;
            RectForTouch.Height = ImageHeight;
            RectForTouch.Fill = Brushes.Transparent;
            RectForTouch.PreviewTouchDown += new EventHandler<TouchEventArgs>(RectForTouch_PreviewTouchDown);
        }

        void RectForTouch_PreviewTouchDown(object sender, TouchEventArgs e)
        {
            //通知被點擊
            SendInfoToLiveContainer(indexOfEvent, CurrentShowIndex - 1);
        }

        /// <summary>
        /// 該PlaneRotate 顯示資訊
        /// </summary>
        public void startShow()
        {
            //將紀錄設定為第一筆資料 <一開始會先顯示的資料>
            RecordInfoCount = 1;
            //一開始先顯示圖片或者文字(亂數取)
            CurrentShowIndex = rnd.Next(0, ElementForRotateList.Count);
            //透過索引值~改變要顯示的是該月份的第幾個資料~文字或者圖~?
            ChangeElementForShow(ref CurrentShowIndex);
        }

        /// <summary>
        /// 停止該PlaneRotate自轉模式
        /// </summary>
        public void stopShow()
        {
            //清除所有顯示資訊
            uxRotateContain.Children.Clear();
            ElementForRotateList.Clear();
            RotateWaitTime.Stop();
        }

        /// <summary>
        /// 取得下次要翻轉的等待時間 (翻轉開始呼叫函數~)
        /// </summary>
        public void StartCountDownForRatate()
        {
            //亂數取得
            int time = rnd.Next(changeInfoTimeMin, changeInfoTimeMax);

            RotateWaitTime.Interval = TimeSpan.FromSeconds(time);
            RotateWaitTime.Start();
        }

        //如果等待時間到~則開始旋轉並在設定其下次要旋轉的等待時間
        void RotateWaitTime_Tick(object sender, EventArgs e)
        {
            RotateWaitTime.Stop();
            StartCountDownForRatate();
            RotateTheObject();

            #region 判斷是否資料已經到底
            //該遍資料紀錄值加一
            RecordInfoCount++;
            //判斷該資料是否已經到底了~如果是~則通知 LiveContainer
            CheckTheFileEndToSend(ref RecordInfoCount);

            #endregion
        }

        /// <summary>
        /// 停止翻轉功能
        /// </summary>
        public void StopCountDownForRatate()
        {
            RotateWaitTime.Stop();
        }

        /// <summary>
        /// 先將可以顯示的資訊放到 ElementForRotateList 中
        /// </summary>
        private void AddRotateInfoToList()
        {
            ElementForRotateList.Clear();
            #region 先加文字
            Grid gridfortext = new Grid();
            TextBlock textblock = new TextBlock();

            if (ConfigSettingClass.MainBackCollect.DefaultLangIndex < ConfigSettingClass.MainBackCollect.LangFlowDir.Length)
            {
                textblock.FlowDirection = ConfigSettingClass.MainBackCollect.LangFlowDir[ConfigSettingClass.MainBackCollect.DefaultLangIndex];
            }

            try
            {
                //假如現在是第一種語系
                if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language1")
                {
                    textblock.Text = RotateMonthClass.titleLan1;
                }
                else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language2")
                {
                    textblock.Text = RotateMonthClass.titleLan2;
                }
                else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language3")
                {
                    textblock.Text = RotateMonthClass.titleLan3;
                }
                else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language4")
                {
                    textblock.Text = RotateMonthClass.titleLan4;
                }
            }
            catch
            {

            }

            gridfortext.VerticalAlignment = System.Windows.VerticalAlignment.Center;
            gridfortext.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            gridfortext.Width = ImageWidth;
            gridfortext.Height = ImageHeight;
            textblock.TextWrapping = TextWrapping.Wrap;
            textblock.FontSize = TextFontSize;
            textblock.Foreground = RotateContainTextColor;
            textblock.Margin = new Thickness(10);
            gridfortext.Children.Add(textblock);

            ElementForRotateList.Add(gridfortext);
            #endregion

            #region 加圖片
            //做法 : 先將 imagepath 路徑下的圖片縮圖, 之後放到 image controller 下再放到 ElementForRotateList 中
            if (RotateMonthClass.imagepath != "")
            {
                string[] tempFile;

                if (Directory.Exists(GlobalFunction.EventFileImgPath + RotateMonthClass.imagepath))
                {
                    tempFile = Directory.GetFiles(GlobalFunction.EventFileImgPath + RotateMonthClass.imagepath);

                    // tempFile 為全部的圖片張數，避免記憶體吃太多~ 每個事件框以亂數載入五張為最多
                    int startupIndex = 0;
                    int targetIndex = 0;
                    bool startGet = true;
                    int maxLoadValue = 5;

                    if (tempFile.Count() > maxLoadValue)
                    {
                        startGet = false;
                        startupIndex = rnd.Next(0, tempFile.Count() - maxLoadValue);
                    }

                    foreach (string item in tempFile)
                    {
                        if (targetIndex != startupIndex && !startGet)
                        {
                            targetIndex++;
                        }
                        else
                        {
                            // 開始取圖
                            startGet = true;
                            if (maxLoadValue < 0)
                                break;
                            maxLoadValue--;
                            if (imgfilter.Contains(System.IO.Path.GetExtension(item).ToLower()))
                            {
                                Grid gd = new Grid();
                                Image img = new Image();
                                FileInfo fileinfo = new FileInfo(item);
                                string FilePath = fileinfo.FullName.ToString().Trim();

                                RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality);
                                img.Source = MediaViewerLib.Utilities.MediaUtilties.LoadBitmapImage(FilePath, ImageWidth);
                                img.Stretch = Stretch.UniformToFill;
                                img.VerticalAlignment = System.Windows.VerticalAlignment.Center;
                                img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
                                gd.Width = ImageWidth;
                                gd.Height = ImageHeight;
                                gd.Children.Add(img);

                                ElementForRotateList.Add(gd);
                            }
                            else if (mediafilter.Contains(System.IO.Path.GetExtension(item).ToLower()))
                            {
                                Grid gd = new Grid();
                                Image img = new Image();
                                FileInfo fileinfo = new FileInfo(item);
                                string FilePath = fileinfo.FullName.ToString().Trim();

                                // 影片取縮圖
                                RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality);
                                ShellFile shellFile = ShellFile.FromFilePath(FilePath);
                                BitmapSource shellThumb = shellFile.Thumbnail.ExtraLargeBitmapSource;
                                img.Source = shellThumb;
                                img.Stretch = Stretch.UniformToFill;
                                img.VerticalAlignment = System.Windows.VerticalAlignment.Center;
                                img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
                                gd.Width = ImageWidth;
                                gd.Height = ImageHeight;
                                gd.Children.Add(img);

                                ElementForRotateList.Add(gd);
                            }
                        }
                    }
                }
            }
            #endregion

            #region 加預設logo圖
            //如果以上圖文只有一個有資料~則加上預設的圖
            if (ElementForRotateList.Count <= 1 && ConfigSettingClass.MainBackCollect.ImgLogo != "")
            {
                string DefaultLogoPath = ConfigSettingClass.MainBackCollect.ImgLogo;

                if (File.Exists(GlobalFunction.thumbPath + DefaultLogoPath))
                {
                    Grid gd = new Grid();
                    Image img = new Image();

                    img.Source = MediaViewerLib.Utilities.MediaUtilties.LoadBitmapImage(GlobalFunction.thumbPath + DefaultLogoPath, ImageWidth);
                    img.Stretch = Stretch.Uniform;
                    img.VerticalAlignment = System.Windows.VerticalAlignment.Center;
                    img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
                    gd.Width = ImageWidth;
                    gd.Height = ImageHeight;
                    gd.Children.Add(img);

                    ElementForRotateList.Add(gd);
                }
            }
            #endregion
            SendChangeBlockIndex("Load Complete", 0);
        }

        /// <summary>
        /// 增加事件~增加從 LiveContainer Callback Event
        /// </summary>
        /// <param name="liveContainer"></param>
        public void ListenFromLiveContainerCode(LiveContainer liveContainer)
        {
            liveContainer.LiveContainerBubbleToPlaneRotateEvent += new LiveContainer.LiveContainerBubbleToPlaneRotateMap(ReceiveFromLiveContainerForFileChange);
        }

        /// <summary>
        /// 將該索引加到uxRotateContain
        /// </summary>
        /// <param name="CurrentShowIndex">指向 ElementForRotateList 中的索引值</param>
        private void ChangeElementForShow(ref int index)
        {
            uxRotateContain.Children.Clear();

            if (index >= ElementForRotateList.Count)
            {
                //超過資料上限~重頭播放
                index = 0;
            }
            if (ElementForRotateList.Count == 0)
            {
                return;
            }
            uxRotateContain.Children.Add(ElementForRotateList[index]);
        }

        /// <summary>
        /// 取得圖片Source
        /// </summary>
        /// <param name="imgpath">指定圖片路徑</param>
        /// <returns></returns>
        private ImageSource GetBitmapImage(string imgpath)
        {
            BitmapImage bitmapImg = new BitmapImage();

            bitmapImg.BeginInit();
            bitmapImg.UriSource = new Uri(imgpath, UriKind.RelativeOrAbsolute);
            //忽略原始圖檔的色盤設定，使用預設值，可縮短載入圖檔的時間
            //如有遇到色彩不正確的問題，或者原圖有特殊的自定義色盤，請不要使用此設定
            bitmapImg.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
            //使用以下的預先載入設定，在BitmapImage創建完成之後，可立刻釋放其所占用或鎖住的資源，以免咬住檔案
            bitmapImg.CacheOption = BitmapCacheOption.OnLoad;
            //根據欲顯示的區域長或寬，來設定 DecodePixelHeight 或 DecodePixelWidth 的值
            //bitmapImg.DecodePixelHeight = THUMB_HEIGHT;
            //bitmapImg.DecodePixelWidth = THUMB_WIDTH;
            bitmapImg.EndInit();
            bitmapImg.Freeze();

            return bitmapImg;
        }
    }
}
