using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Xml.Linq;

namespace FlickrSlideShow
{
    public partial class Page : UserControl
    {
        // Variablen für die Flickr-Anbindung
        IEnumerable<FlickrImage> images;
        private string searchText; 

        // Variablen für Drag & Drop
        private Point mousePosition;
        private bool isDragging = false;

        // Variablen für die Slideshow
        int imageIndex = 0;
        private bool isSlideshow = false; 
        private DispatcherTimer slideshowTimer = new DispatcherTimer();
        

        public Page()
        {
            InitializeComponent();
            imageOverview.Visibility = Visibility.Visible;

            fadeOutAnimation.Completed += new EventHandler(fadeOutAnimation_Completed);

            slideshowTimer.Interval = new TimeSpan(0, 0, 0, 0, 5000); 
            slideshowTimer.Tick += new EventHandler(slideshowTimer_Tick);
        }

        // Methoden für die Flickr-Anbindung
        private void searchButton_Click(object sender, RoutedEventArgs e)
        {
            searchText = searchInput.Text; 
            loadImages(searchText);
        }

        void loadImages(string topic)
        {
            //string apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // bitte eigenen API-Key anfordern!
            string flickrUrl = String.Format("http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key={1}&text={0}", topic, apiKey);
            WebClient flickrService = new WebClient();
            flickrService.DownloadStringCompleted += new DownloadStringCompletedEventHandler(flickrService_DownloadStringCompleted);
            flickrService.DownloadStringAsync(new Uri(flickrUrl));
            searchInput.Text = "Bilder werden geladen...";
        }

        void flickrService_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            XDocument xmlImages = XDocument.Parse(e.Result);
            if (e.Error != null ||
                xmlImages.Element("rsp").Attribute("stat").Value == "fail")
            {
                searchInput.Text = "Fehler! (" + e.Result + ")";
                return;
            }
            else
            {
                searchInput.Text = searchText;
                stopSlideShow();
                imageOverview.Children.Clear();
                thumbnailContainer.Children.Clear();
                images = from photo in xmlImages.Element("rsp").Element("photos").Descendants().ToList()
                         select new FlickrImage
                         {
                             Id = (string)photo.Attribute("id"),
                             Secret = (string)photo.Attribute("secret"),
                             Server = (string)photo.Attribute("server"),
                             Farm = (string)photo.Attribute("farm"),
                         };
                initializeThumbnails();
            }
        }

        private void initializeThumbnails()
        {
            int row, column;
            int index;
            int rowCount = imageOverview.RowDefinitions.Count;
            int columnCount = imageOverview.ColumnDefinitions.Count;

            FlickrImage flickrImage;
            Thumbnail thumbnail;

            for (row = 0; row < rowCount; row++)
            {
                for (column = 0; column < columnCount; column++)
                {
                    index = row * columnCount + column;
                    flickrImage = images.Skip(index).First();
                    thumbnail = createThumbnail(flickrImage.ImageUrl, row, column);
                    imageOverview.Children.Add(thumbnail);
                }
            }
        }

        private Thumbnail createThumbnail(String imageUrl, int row, int column)
        {
            Thumbnail newThumbnail = new Thumbnail(imageUrl);

            newThumbnail.SetValue(Grid.ColumnProperty, column);
            newThumbnail.SetValue(Grid.RowProperty, row);

            newThumbnail.MouseLeftButtonDown += new MouseButtonEventHandler(thumbnail_MouseLeftButtonDown);
            newThumbnail.MouseMove += new MouseEventHandler(thumbnail_MouseMove);
            newThumbnail.MouseLeftButtonUp += new MouseButtonEventHandler(thumbnail_MouseLeftButtonUp);

            return newThumbnail; 
        }

        // Methoden für Drag & Drop
        void thumbnail_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            Thumbnail thumb = sender as Thumbnail; 
            Point clickPosition; 

            if (fe != null)
            {
                isDragging = true;
                mousePosition = e.GetPosition(null);
                clickPosition = e.GetPosition(thumb.thumbnailImage as UIElement);

                fe.CaptureMouse();
                fe.Cursor = Cursors.Hand;

                (fe.Parent as Panel).Children.Remove(fe);
                dragLayer.Children.Add(fe);

                fe.SetValue(Canvas.LeftProperty, mousePosition.X - clickPosition.X);
                fe.SetValue(Canvas.TopProperty, mousePosition.Y - clickPosition.Y);
            }
        }

        void thumbnail_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            List<UIElement> hitElements = (List<UIElement>)HitTest(e.GetPosition(null));
            UIElement scroller = this.scroller as UIElement;

            fe.ReleaseMouseCapture();
            fe.Cursor = null;
            isDragging = false;
            dragLayer.Children.Remove(fe);

            if (hitElements.Contains(scroller))
            {
                thumbnailContainer.Children.Add(fe);
            }
            else 
            {
                imageOverview.Children.Add(fe);
            }
            if (thumbnailContainer.Children.Count > 0)
            {
                this.selectionLabel.Visibility = Visibility.Collapsed;
                this.slideshowButton.Visibility = Visibility.Visible; 
            }
            else
            {
                this.selectionLabel.Visibility = Visibility.Visible;
                this.slideshowButton.Visibility = Visibility.Collapsed;
            }
            mousePosition.X = mousePosition.Y = 0;
        }

        void thumbnail_MouseMove(object sender, MouseEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            Point currentPosition = e.GetPosition(null);

            if (isDragging)
            {
                double deltaV = currentPosition.Y - mousePosition.Y;
                double deltaH = currentPosition.X - mousePosition.X;
                double newTop = deltaV + (double)fe.GetValue(Canvas.TopProperty);
                double newLeft = deltaH + (double)fe.GetValue(Canvas.LeftProperty);

                fe.SetValue(Canvas.TopProperty, newTop);
                fe.SetValue(Canvas.LeftProperty, newLeft);

                mousePosition = currentPosition;
            }
        }

        // Methoden für die Slideshow
        private void slideshowButton_Click(object sender, RoutedEventArgs e)
        {
            if (isSlideshow == false)
            {
                startSlideShow();
            }
            else
            {
                stopSlideShow();
            }
        }

        private void startSlideShow()
        {
            isSlideshow = true;
            imageIndex = 0; 
            imageOverview.Visibility = Visibility.Collapsed;
            scroller.Visibility = Visibility.Collapsed;
            slideshowImage.Opacity = 0; 
            slideshowImage.Visibility = Visibility.Visible;
            slideshowButton.Content = "Slideshow anhalten";
            showNextSlide();
            slideshowTimer.Start();
        }

        private void stopSlideShow()
        {
            slideshowTimer.Stop();
            isSlideshow = false;
            slideshowImage.Visibility = Visibility.Collapsed;
            imageOverview.Visibility = Visibility.Visible;
            scroller.Visibility = Visibility.Visible;
            slideshowButton.Content = "Slideshow starten";
        }

        private void showNextSlide()
        {
            UIElementCollection slideshowImages = thumbnailContainer.Children;
            Thumbnail currentThumbnail;

            if (slideshowImages == null) return;
            if (imageIndex >= slideshowImages.Count) imageIndex = 0;

            currentThumbnail = (Thumbnail) slideshowImages.Skip(imageIndex).First();
            setImageSource(currentThumbnail.ImageSource, slideshowImage);

            fadeInAnimation.Begin();

            imageIndex++;
        }

        private void setImageSource(string url, Image imageControl)
        {
            Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
            BitmapImage bitmap = new BitmapImage(uri);
            imageControl.SetValue(Image.SourceProperty, bitmap);
        }

        private void slideshowTimer_Tick(object sender, EventArgs e)
        {
            fadeOutAnimation.Begin(); 
        }

        private void fadeOutAnimation_Completed(object sender, EventArgs e)
        {
            showNextSlide(); 
        }

    }
}
