using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Phone.BackgroundAudio;
using System.IO.IsolatedStorage;
using System.Windows.Resources;
using Microsoft.Phone.Shell;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Diagnostics;

namespace BackgroundAudioPlayerSample
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Zeitgeber fuer die Aktualisierung des Fortschrittsbalkens
        private DispatcherTimer myDispatcherTimer;

        // Hauptkonstruktor
        public MainPage()
        {
            InitializeComponent();

            // Audiodateien in den Isolated Storage kopieren
            CopyToIsolatedStorage();

            // PlayStateChanged-Ereignis initialisieren
            BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);

            // Zeitgeber mit entsprechendem Ereignis initialisieren
            myDispatcherTimer = new DispatcherTimer();
            myDispatcherTimer.Interval = TimeSpan.FromSeconds(0.5);
            myDispatcherTimer.Tick += new EventHandler(myDispatcherTimer_Tick);
        }

        // Ereignismethode des Zeitgebers
        void myDispatcherTimer_Tick(object sender, EventArgs e)
        {
            if (BackgroundAudioPlayer.Instance.Track != null)
            {
                // wenn die Trackinfos gesetzt wurden und das Maximum des Fortschrittbalkens ungleich der Gesamtsekunden der Dauer ist, dann Gesamtsekunden der Dauer als Maximum des Fortschrittbalkens setzen
                if (BackgroundAudioPlayer.Instance.Track.Duration.TotalSeconds != 0 && pgb_Duration.Maximum != BackgroundAudioPlayer.Instance.Track.Duration.TotalSeconds)
                    pgb_Duration.Maximum = BackgroundAudioPlayer.Instance.Track.Duration.TotalSeconds;

                // aktuelle Abspielposition im Fortschrittbalken setzen
                pgb_Duration.Value = BackgroundAudioPlayer.Instance.Position.TotalSeconds;

                // aktuelle Position anzeigen
                tbk_CurrentPosition.Text = string.Format("{0:00}:{1:00}:{2:00}", BackgroundAudioPlayer.Instance.Position.TotalHours, BackgroundAudioPlayer.Instance.Position.TotalMinutes, BackgroundAudioPlayer.Instance.Position.Seconds);
            }
        }

        // Ereignismethode fuer die Aenderung des Wiedergabestatus
        void Instance_PlayStateChanged(object sender, EventArgs e)
        {
            // Wiedergabestatus auswerten
            switch (BackgroundAudioPlayer.Instance.PlayerState)
            {
                // Wiedergabe wurde pausiert
                case PlayState.Paused:
                    // Zeitgeberereignisbehandlung durchführen
                    myDispatcherTimer_Tick(null, null);
                    // Zeitgeber anhalten
                    myDispatcherTimer.Stop();
                    // Schaltflaechen setzen
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[1]).IsEnabled = true;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[3]).IsEnabled = false;
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    break;

                // Wiedergabe laeuft
                case PlayState.Playing:
                    // wenn das Maximum des Fortschrittbalkens ungleich der Gesamtsekunden der Dauer ist, dann Gesamtsekunden der Dauer als Maximum des Fortschrittbalkens setzen
                    if (pgb_Duration.Maximum != BackgroundAudioPlayer.Instance.Track.Duration.TotalSeconds)
                        pgb_Duration.Maximum = BackgroundAudioPlayer.Instance.Track.Duration.TotalSeconds;

                    // Zeitgeberereignisbehandlung durchführen
                    myDispatcherTimer_Tick(null, null);
                    // Zeitgeber starten
                    myDispatcherTimer.Start();
                    // Schaltflaechen setzen
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Pausieren";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.pause.rest.png", UriKind.Relative);
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = true;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[1]).IsEnabled = true;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[3]).IsEnabled = true;
                    btn_FastForward.IsEnabled = true;
                    btn_Rewind.IsEnabled = true;
                    break;

                    // Wiedergabe wurde gestoppt
                case PlayState.Stopped:
                    // Zeitgeber anhalten
                    if (myDispatcherTimer.IsEnabled)
                        myDispatcherTimer.Stop();
                    // Fortschrittsbalken zuruecksetzen
                    pgb_Duration.Value = 0;
                    // Positionsangabe loeschen
                    tbk_CurrentPosition.Text = string.Empty;
                    // Schaltflaechen setzen
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[1]).IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[3]).IsEnabled = false;
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    // Song auf Null setzen
                    BackgroundAudioPlayer.Instance.Track = null;
                    break;
        
                    // Wiedergabe wird zurückgespult
                case PlayState.Rewinding:
                    // Zeitgeber anhalten
                    myDispatcherTimer.Stop();
                    // Schaltflaechen setzen
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    break;

                // Wiedergabe wird vorgespult
                case PlayState.FastForwarding:
                    // Zeitgeber anhalten
                    myDispatcherTimer.Stop();
                    // Schaltflaechen setzen
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    break;
            }

            // Songinformation in UI setzen
            SetTrackInfoInGUI();
        }

        // Ereignismethode, die beim Anzeigen der Anwendung aufgerufen wird
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            // Lautstaerke der Hintergrundwiedergabe fuer den Schieberegler setzen
            sld_Volume.Value = BackgroundAudioPlayer.Instance.Volume;

            // Wiedergabestatus auswerten
            switch (BackgroundAudioPlayer.Instance.PlayerState)
            {
                case PlayState.Paused:
                    pgb_Duration.Maximum = BackgroundAudioPlayer.Instance.Track.Duration.TotalSeconds;
                    // Zeitgeberereignisbehandlung durchführen
                    myDispatcherTimer_Tick(null, null);

                    // Schaltflaechen setzen, wenn Wiedergabe pausiert wurde
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[1]).IsEnabled = true;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[3]).IsEnabled = false;
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    break;

                case PlayState.Playing:
                    pgb_Duration.Maximum = BackgroundAudioPlayer.Instance.Track.Duration.TotalSeconds;
                    // Zeitgeberereignisbehandlung durchführen
                    myDispatcherTimer_Tick(null, null);
                    myDispatcherTimer.Start();

                    // Schaltflaechen setzen, wenn Wiedergabe gerade laeuft
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Pausieren";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.pause.rest.png", UriKind.Relative);
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = true;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[1]).IsEnabled = true;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[3]).IsEnabled = true;
                    btn_FastForward.IsEnabled = true;
                    btn_Rewind.IsEnabled = true;
                    break;

                case PlayState.Stopped:
                    pgb_Duration.Value = 0;

                    // Schaltflaechen setzen, wenn Wiedergabe gestoppt wurde
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[1]).IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[3]).IsEnabled = false;
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    break;

                case PlayState.Rewinding:
                    // Schaltflaechen setzen, wenn Wiedergabe zurueckgespult wird
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    break;

                case PlayState.FastForwarding:
                    // Schaltflaechen setzen, wenn Wiedergabe vorgespult wird
                    btn_FastForward.IsEnabled = false;
                    btn_Rewind.IsEnabled = false;
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).Text = "Abspielen";
                    ((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBarIcons/appbar.transport.play.rest.png", UriKind.Relative);
                    break;
            }

            // aktuelle Songinformationen setzen
            SetTrackInfoInGUI();

            // Lautstaerke setzen
            sld_Volume_ValueChanged(null, null);
        }

        // Methode um die Audiodatei vom Anwendungsordner in den Isolated Storage zu kopierten
        private void CopyToIsolatedStorage()
        {
            using (IsolatedStorageFile myIsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                // Namen der Audiodateien, die vom Anwendungsordner in den Isolated Storage kopiert werden sollen
                string[] audiofiles = new string[] { "sample.wma" , "sample.mp3" };

                foreach (var audiofile in audiofiles)
                {
                    // pruefen, ob Datei bereits im Isolated Storage existiert
                    if (!myIsolatedStorageFile.FileExists(audiofile))
                    {
                        // Audiodatei aus Anwendungsverzeichnis assoziieren
                        StreamResourceInfo myStreamResourceInfo = Application.GetResourceStream(new Uri("Audiofiles/" + audiofile, UriKind.Relative));
                        // pruefen, ob Audiodatei assoziiert werden konnte
                        if (myStreamResourceInfo != null)
                        {
                            // Datei im Isolated Storage erstellen
                            using (IsolatedStorageFileStream myIsolatedStorageFileStream = myIsolatedStorageFile.CreateFile(audiofile))
                            {
                                int chunkSize = 4096;
                                byte[] bytes = new byte[chunkSize];
                                int byteCount;

                                // Audiodatei aus Anwendungsordner in den Isolated Storage kopieren 
                                while ((byteCount = myStreamResourceInfo.Stream.Read(bytes, 0, chunkSize)) > 0)
                                {
                                    myIsolatedStorageFileStream.Write(bytes, 0, byteCount);
                                }
                            }
                        }
                        else
                        {
                            MessageBox.Show("Die Datei '" + audiofile + "' wurde im Anwendungsverzeichnis nicht gefunden!", "Fehler", MessageBoxButton.OK);
                        }
                    }                   
                }
            }
        }

        // Methode zum Setzen der aktuellen Songinformationen
        private void SetTrackInfoInGUI()
        {
            // pruefen, ob sich derzeit ein Song im BackgroundAudioPlayer befindet
            if (BackgroundAudioPlayer.Instance.Track != null)
            {
                // aktuelle Songinformationen setzen
                tbk_Title.Text = BackgroundAudioPlayer.Instance.Track.Title;
                tbk_Artist.Text = BackgroundAudioPlayer.Instance.Track.Artist;
                tbk_Album.Text = BackgroundAudioPlayer.Instance.Track.Album;
                
                // pruefen, ob eine URL als Cover angegeben wurde
                if (BackgroundAudioPlayer.Instance.Track.AlbumArt != null)
                {
                    // URL als Bild setzen
                    img_AlbumArt.Source = new BitmapImage(BackgroundAudioPlayer.Instance.Track.AlbumArt);
                }
                else
                {
                    // Kein Cover Bild setzen
                    img_AlbumArt.Source = new BitmapImage(new Uri("NoCover.png", UriKind.Relative));
                }

                tbk_Duration.Text = string.Format("{0:00}:{1:00}:{2:00}", BackgroundAudioPlayer.Instance.Track.Duration.TotalHours, BackgroundAudioPlayer.Instance.Track.Duration.TotalMinutes, BackgroundAudioPlayer.Instance.Track.Duration.Seconds);
                tbk_Source.Text = BackgroundAudioPlayer.Instance.Track.Source.OriginalString;
            }
            else
            {
                // Anzeigewerte löschen
                tbk_Title.Text = "";
                tbk_Artist.Text = "";
                tbk_Album.Text = "";
                tbk_Duration.Text = "";
                tbk_Source.Text = "";
                img_AlbumArt.Source = null;
            }
        }

        // Ereignismethode der Abspielen-Schaltflaeche
        private void abib_Play_Click(object sender, EventArgs e)
        {
            BackgroundAudioPlayer.Instance.Volume = 1;
            // pruefen, ob der BackgroundAudioPlayer gerade etwas wiedergibt
            if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing)
                // Wiedergabe pausieren
                BackgroundAudioPlayer.Instance.Pause();
            else
                // Wiedergabe starten bzw. fortsetzen
                BackgroundAudioPlayer.Instance.Play();
        }

        // Ereignismethode der Stoppen-Schaltflaeche
        private void abib_Stop_Click(object sender, EventArgs e)
        {
            // Wiedergabe stoppen
            BackgroundAudioPlayer.Instance.Stop();
        }

        // Ereignismethode der Vorheriger-Schaltflaeche
        private void abib_Previous_Click(object sender, EventArgs e)
        {
            // vorherigen Song wiedergeben
            BackgroundAudioPlayer.Instance.SkipPrevious();
        }

        // Ereignismethode der Next-Schaltflaeche
        private void abib_Next_Click(object sender, EventArgs e)
        {
            // naechsten Song wiedergeben
            BackgroundAudioPlayer.Instance.SkipNext();
        }

        // Ereignismethode des Lautstaerkeschieberegler
        private void sld_Volume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if(sld_Volume != null)
                // Wert fuer Lautstaerke setzen            
                BackgroundAudioPlayer.Instance.Volume = sld_Volume.Value;
        }

        // Ereignismethode der Zurueckspulen-Schaltflaeche
        private void btn_Rewind_Click(object sender, RoutedEventArgs e)
        {
            // aktuelle Wiedergabe zurueckspulen
            BackgroundAudioPlayer.Instance.Rewind();
        }

        // Ereignismethode der Vorspulen-Schaltflaeche
        private void btn_FastForward_Click(object sender, RoutedEventArgs e)
        {
            // aktuelle Wiedergabe vorspulen
            BackgroundAudioPlayer.Instance.FastForward();
        }
    }
}