using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.ComponentModel;
using System.Reflection;
using System.Collections.Generic;

using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using FingersDance.Factory;
using FingersDance.Actions;
using FingersDance.Control.TimeLine;
using FingersDance.Views;
using FingersDance.ViewModels;
using GestureControl;

namespace FingersDance.Control.Player
{
	public partial class UserControlPlayer
	{
        #region Variables
        private bool isPlaying = false;
        #endregion

        public event EventHandler PlayerOpened;
        public event EventHandler PlayerStopOrPause;
        public event EventHandler NewGestureRegognized;

        double _Time = 0;
        double _StartAnnotation = -1;
        List<Gesture> _Gestures = new List<Gesture>();

        public double Time
        {
            get { return gestureControl.time; }
            set
            {
                gestureControl.time = value;
                _Time = value;
            }
        }

        #region constructors
        public UserControlPlayer()
        {
            this.InitializeComponent();
            MediaElementVideo.LoadedBehavior = MediaState.Manual;
            MediaElementVideo.UnloadedBehavior = MediaState.Manual;
            //SAR
            //Control User Info
            usercontrolInfoUser.LabelSession.Content = "Seance Test";
            usercontrolInfoUser.LabelUser.Content = "User Test";
            MediaElementVideo.Volume = 0;
        }

        #endregion

        #region Properties
        public double TotalMilliseconds
        {
            get
            {
                return MediaElementVideo.NaturalDuration.TimeSpan.TotalMilliseconds;
            }
        }
        public MediaElement Player
        {
            get
            {
                return MediaElementVideo;
            }
            set
            {
                MediaElementVideo= value;
            }
        }
        #endregion


        #region Methodes

        public void initPlayer(string path)
        {
            //init player
            isPlaying = false;
            MediaElementVideo.Source = new Uri(path);
            MediaElementVideo.ScrubbingEnabled = true;
        }

        public void playerPause()
        {
            MediaElementVideo.Pause();
            if (PlayerStopOrPause != null)
                PlayerStopOrPause(false, new EventArgs());
        }
        public void playerPlay()
        {
            MediaElementVideo.Play();
            if (PlayerStopOrPause != null)
                PlayerStopOrPause(true, new EventArgs());
        }
        public void playerStop()
        {
            MediaElementVideo.Stop();
            if (PlayerStopOrPause != null)
                PlayerStopOrPause(false, new EventArgs());
        }

        public void setSound(double val)
        {
            if ((val < 1) && (val > 0))
                MediaElementVideo.Volume = val;
            else if (val >= 1)
                MediaElementVideo.Volume = 1;
            else
                MediaElementVideo.Volume = 0;
        }

        public void setMute(bool b)
        {
            if (b) MediaElementVideo.IsMuted = true;
            else MediaElementVideo.IsMuted = false;
        }
        #endregion

        #region GestureEvents

        public void GestureDetected(object sender, GestureControl.GestureRoutedEventArgs e)
        {
            try
            {
                /*
                 *  e.Gesture.Name = Nom de la gesture
                 *  e.Gesture.Start = Valeur de la timeline au début de l'annotation
                 *  e.Gesture.End = Valeur de la timeline à la fin de l'annotation
                 * 
                 */
                switch (e.Gesture.Name)
                {
                    case "TRIGGER":

                        usercontrolInfoUser.LabelSession.Content = "TRIGGER!";
                        break;
                    case "CONTRE POINTS":

                        usercontrolInfoUser.LabelSession.Content = "CONTRE POINTS!";
                        break;
                    case "CONTRE PESANTEUR":

                        usercontrolInfoUser.LabelSession.Content = "CONTRE PESANTEUR!";
                        break;
                    case "AVEC PESANTEUR":

                        usercontrolInfoUser.LabelSession.Content = "AVEC PESANTEUR!";
                        break;
                    case "ALIGNEMENT":

                        usercontrolInfoUser.LabelSession.Content = "ALIGNEMENT!";
                        break;
                    case "CONTACT VISUEL":

                        usercontrolInfoUser.LabelSession.Content = "CONTACT VISUEL!";
                        break;
                    case "MOUVEMENT CONTRAINTE":

                        usercontrolInfoUser.LabelSession.Content = "MOUVEMENT CONTRAINTE!";
                        break;
                    case "UN DANSEUR":

                        usercontrolInfoUser.LabelSession.Content = "UN DANSEUR!";
                        break;
                    case "DEUX DANSEURS":

                        usercontrolInfoUser.LabelSession.Content = "DEUX DANSEURS!";
                        break;
                    case "TROIS DANSEURS":

                        usercontrolInfoUser.LabelSession.Content = "TROIS DANSEURS!";
                        break;
                    case "QUATRE DANSEURS":

                        usercontrolInfoUser.LabelSession.Content = "QUATRE DANSEURS!";
                        break;
                    case "TOUS LES DANSEURS":

                        usercontrolInfoUser.LabelSession.Content = "TOUS LES DANSEURS!";
                        break;
                    case "CONTACT TABLE/DANSEUR":

                        usercontrolInfoUser.LabelSession.Content = "CONTACT TABLE/DANSEUR!";
                        break;
                    case "PLAY-PAUSE":
                        usercontrolInfoUser.LabelSession.Content = "PLAY-PAUSE!";
                        ButtonPlayPause_ContactDown(null, null);
                        break;
                    default:
                        return;
                }
                if (!e.Gesture.Name.Equals("PLAY-PAUSE"))
                    _Gestures.Add(e.Gesture);
            }
            catch { }
        }
        #endregion

        #region Button Simple Player Actions
        private void ButtonPlayPause_ContactDown(object sender, Microsoft.Surface.Presentation.ContactEventArgs e)
        {
            if (!isPlaying)//Play
            {
                isPlaying = true;
                try
                {
                    MediaElementVideo.Play();
                    if (PlayerStopOrPause != null)
                        PlayerStopOrPause(true, new EventArgs());
                }
                catch (Exception ex) { }
            }
            else//Pause
            {
                isPlaying = false;
                try
                {
                    MediaElementVideo.Pause();
                    if (PlayerStopOrPause != null)
                        PlayerStopOrPause(false, new EventArgs());
                }
                catch (Exception exx) { }
            }

        }

        /*
        
        private void ButtonPlayPause_Click(object sender, RoutedEventArgs e)
        {
            if (!isPlaying)//Play
            {
                isPlaying = true;
                try
                {
                    MediaElementVideo.Play();
                    if (PlayerStopOrPause != null)
                        PlayerStopOrPause(true, new EventArgs());
                }
                catch (Exception ex) { }

            }
            else//Pause
            {
                isPlaying = false;
                try
                {
                    MediaElementVideo.Pause();
                    if (PlayerStopOrPause != null)
                        PlayerStopOrPause(false, new EventArgs());
                }
                catch (Exception exx) { }
                //ButtonPlayPause.Background = FindResource("[Skin_1]_Play_button_xaml") as Brush;
            }
        }

        private void ButtonFastForward_Click(object sender, RoutedEventArgs e)
        {
            if (MediaElementVideo.SpeedRatio <= 3)
                MediaElementVideo.SpeedRatio += 1;
        }

        private void ButtonFastForward_ContactDown(object sender, Microsoft.Surface.Presentation.ContactEventArgs e)
        {
            if (MediaElementVideo.SpeedRatio <= 3)
                MediaElementVideo.SpeedRatio += 1;
        }

        private void ButtonRewind_Click(object sender, RoutedEventArgs e)
        {
            //TimeSpan ts = new TimeSpan(0, 0, 0, 0);
            if (MediaElementVideo.SpeedRatio > 1)
            {
                MediaElementVideo.SpeedRatio -= 1;
            }
            else
            {
                MediaElementVideo.Position = MediaElementVideo.Position.Add(new TimeSpan(0, 0, 0, -5));
            }
        }

        private void ButtonRewind_ContactDown(object sender, Microsoft.Surface.Presentation.ContactEventArgs e)
        {

            //TimeSpan ts = new TimeSpan(0, 0, 0,0);
            if (MediaElementVideo.SpeedRatio > 1)
            {
                MediaElementVideo.SpeedRatio -= 1;
            }
            else
            {
                MediaElementVideo.Position = MediaElementVideo.Position.Add(new TimeSpan(0, 0, 0, -5));
            }
        }
        
        */

        #endregion

        private void MediaElementVideo_MediaOpened(object sender, RoutedEventArgs e)
        {
            OnPlayerOpened();
        }
        protected virtual void OnPlayerOpened()
        {
            if(PlayerOpened!=null)
                PlayerOpened(this, new EventArgs());
        }

        private void Play_Pause_area_DragEnter(object sender, SurfaceDragDropEventArgs e)
        {
            //Console.WriteLine("Enter");

            // If the TimelineAnnotationView comes from a user control different from the current one, 
            // it means that we want to add the annotation to the current list.
            // So we check if the dragged annotation can be dragged or if it will recover any existant annotation (in this case it will not be accepted)
            // e.Cursor.DragSource is the SurfaceListBox where the drag started from
            SurfaceListBox slb = (SurfaceListBox)e.Cursor.DragSource;
            // We get the instance of the UserControlSyncSource
            UserControl syncSrc = (UserControl)((Grid)((Grid)this.Parent).Parent).Parent;
            // and its UserControlTimeline
            UserControlTimeLine tl = (UserControlTimeLine)((Grid)((Grid)syncSrc.Content).Children[0]).Children[0];
            if (((Grid)((UserControl)((Grid)slb.Parent).Parent).Parent).Parent != tl)
            {
                // e.Cursor.Visual is the ContentControl, so its Content is the dragged TimelineAnnotationView
                AnnotationViewModel annotationDataVM = (AnnotationViewModel)((TimelineAnnotationView)((ContentControl)e.Cursor.Visual).Content).DataContext;
                //Play_Pause_area.Background = tl.isAnnotationAccepted(annotationDataVM) ? new SolidColorBrush(Colors.Green) : new SolidColorBrush(Colors.Red);
            }
            else
            {
                //Play_Pause_area.Background = new SolidColorBrush(Colors.White);
            }
            //Play_Pause_area.Opacity = 0.3;

        }

        private void Play_Pause_area_DragLeave(object sender, SurfaceDragDropEventArgs e)
        {
            //Console.WriteLine("Leave");
            //Play_Pause_area.Opacity = 0;
        }

        private void Play_Pause_area_DragOver(object sender, SurfaceDragDropEventArgs e)
        {
            //Console.WriteLine("Over");
        }

        private void Play_Pause_area_Drop(object sender, SurfaceDragDropEventArgs e)
        {
            //Console.WriteLine("Drop");
            //Play_Pause_area.Opacity = 0;
            // e.Cursor.Visual is the ContentControl, so its Content is the dragged TimelineAnnotationView
            AnnotationViewModel annotationDataVM = (AnnotationViewModel)((TimelineAnnotationView)((ContentControl)e.Cursor.Visual).Content).DataContext;
            int nbSeconds = (int)annotationDataVM.TcBegin;
            int nbMilliSec = (int)((annotationDataVM.TcBegin * 1000)%1000);
            MediaElementVideo.Position = new TimeSpan(0, 0, 0, nbSeconds, nbMilliSec);


            // If the TimelineAnnotationView comes from a user control different from the current one, 
            // it means that we want to add the annotation to the current list.
            // So we generate the ActionAddAnnotation
            // e.Cursor.DragSource is the SurfaceListBox where the drag started from
            SurfaceListBox slb = (SurfaceListBox)e.Cursor.DragSource;
            // We get the instance of the UserControlSyncSource
            UserControl syncSrc = (UserControl)((Grid)((Grid)this.Parent).Parent).Parent;
            // and its UserControlTimeline
            UserControl tl = (UserControl)((Grid)((Grid)syncSrc.Content).Children[0]).Children[0];
            if (((Grid)((UserControl)((Grid)slb.Parent).Parent).Parent).Parent != tl)
            {
                // Now we build the action arguments : a list holding the timeline and the annotation view models
                List<Object> actionsArgs = new List<Object>();
                actionsArgs.Add(tl);
                actionsArgs.Add(annotationDataVM);

                ActionGenerator ag = new ActionGenerator();
                ActionBase ab = ag.GetAction("ActionAddAnnotation", actionsArgs);
                if (ab != null)
                    ab.Execute();
            }

        }

        public void ApplyColor(List<Color> colors)
        {
            try
            {
                Object o = null;
                rect1.Fill = new SolidColorBrush(Colors.Black);
                o = rect1.FindResource("Rect1Annotation");
                rect1.BeginStoryboard((Storyboard)o);
                rect2.Fill = new SolidColorBrush(Colors.Black);
                o = rect2.FindResource("Rect2Annotation");
                rect2.BeginStoryboard((Storyboard)o);
                rect3.Fill = new SolidColorBrush(Colors.Black);
                o = rect3.FindResource("Rect3Annotation");
                rect3.BeginStoryboard((Storyboard)o);
                rect4.Fill = new SolidColorBrush(Colors.Black);
                o = rect4.FindResource("Rect4Annotation");
                rect4.BeginStoryboard((Storyboard)o);
                for (int i = 1; i <= colors.Count; i++)
                    displayStackPanelAnnotations(i, new SolidColorBrush(colors[i - 1]));
            }
            catch { }
        }

        //This function Sets a brush in a specific rectangle of the StackPanelAnnotation
        public void displayStackPanelAnnotations(int id, Brush brushAnnotation)
        {
            Object o = null;
            switch (id)
            {
                case 1: 
                    rect1.Fill = brushAnnotation;
                    o = rect1.FindResource("Rect1Annotation");
                    rect1.BeginStoryboard((Storyboard)o);
                    break;
                case 2: rect2.Fill = brushAnnotation;
                    o = rect2.FindResource("Rect2Annotation");
                    rect2.BeginStoryboard((Storyboard)o);
                    break;
                case 3: rect3.Fill = brushAnnotation;
                    o = rect3.FindResource("Rect3Annotation");
                    rect3.BeginStoryboard((Storyboard)o);
                    break;
                case 4: rect4.Fill = brushAnnotation;
                    o = rect4.FindResource("Rect4Annotation");
                    rect4.BeginStoryboard((Storyboard)o);
                    break;
                default: break;
            }
        }

        private void AnnotationButton_ContactLeave(object sender, ContactEventArgs e)
        {
            try
            {
                if (_StartAnnotation == -1)
                {
                    _StartAnnotation = _Time;
                    AnnotationLabel.Content = "Annotation en cours";
                }
                else
                {
                    if (NewGestureRegognized != null)
                        NewGestureRegognized(null, new GestureEventArg(_Gestures, _StartAnnotation, _Time));
                    _Gestures.Clear();
                    _StartAnnotation = -1;
                    AnnotationLabel.Content = "";
                    AnnotationButton.IsChecked = false;
                }
            }
            catch { }
        }
	}
}