/// <summary>
 /// Determines whether the specified object is equal to the current object (almost).
 /// </summary>
 /// <param name="obj">The object to compare with the current object.</param>
 /// <returns>
 /// true if the specified object is equal to the current object; otherwise, false.
 /// </returns>
 public bool AlmostEquals(object obj)
 {
     if (obj == null || obj.GetType() != GetType())
     {
         return(base.Equals(obj));
     }
     else
     {
         TMDbDetailExt detailExt = (TMDbDetailExt)obj;
         return
             (Description == detailExt.Description &&
              DetailDescription == detailExt.DetailDescription &&
              Duration == detailExt.Duration &&
              Episode == detailExt.Episode &&
              EpisodeID == detailExt.EpisodeID &&
              FileName == detailExt.FileName &&
              FileSize == detailExt.FileSize &&
              ID == detailExt.ID &&
              ImageFileCache == detailExt.ImageFileCache &&
              ImageFileCacheDir == detailExt.ImageFileCacheDir &&
              ImageFileName == detailExt.ImageFileName &&
              PosterOrStillURL == detailExt.PosterOrStillURL &&
              Season == detailExt.Season &&
              SeasonID == detailExt.SeasonID &&
              VideoPlaybackState == detailExt.VideoPlaybackState);
     }
 }
        // this is called when a video item in the list is clicked..
        private void MoviePanel_Click(object sender, EventArgs e)
        {
            Control       control   = (Control)sender;
            TMDbDetailExt detailExt = (TMDbDetailExt)control.Tag;

            UpdateHighlight(detailExt); // highlight the clicked item and display it's details..
        }
        /// <summary>
        /// Updates the highlighted (selected) video item and displays it's details.
        /// </summary>
        /// <param name="detailExt">An optional TMDbDetailExt class instance of which index to use.</param>
        private void UpdateHighlight(TMDbDetailExt detailExt = null)
        {
            if (detailExt != null)                            // if the optional parameter was given..
            {
                VideoDetailIndex = Videos.IndexOf(detailExt); // get it's index..
            }

            // loop through the video detail panels on the control's video list..
            for (int i = VideoIndex; i < VideoIndex + 5; i++)
            {
                // don't allow "overflow" to happen..
                if (i >= Videos.Count || i >= panels.Count || panels.Count == 0)
                {
                    break;
                }

                // find the border control..
                Control[] controls = panels[i].Controls.Find("Border", false);
                if (controls.Length > 0) // ..and if the border control was found..
                {
                    Panel panel = (Panel)controls[0];
                    // set it's background color to match either highlight or normal border color..
                    panel.BackColor = i == VideoDetailIndex ? HighLilightColor : ItemBorderColor;
                }

                // if the highlighted index is in the collection..
                if (VideoDetailIndex == i)
                {
                    // display the details of the highlighted video..
                    pnPreviewImage.BackgroundImage = Videos[VideoDetailIndex].Image; // set the larger image..
                    lbPreviewImage.Text            = Videos[VideoDetailIndex].Title; // set the title..

                    // set the description..
                    lbDescriptionValue.Text =
                        string.IsNullOrEmpty(Videos[VideoDetailIndex].DetailDescription) ?
                        Videos[VideoDetailIndex].Description : Videos[VideoDetailIndex].DetailDescription;

                    // display the video's length in hours and minutes..
                    lbLengthCaptionAndValue.Text = LengthCaption + " " + Videos[VideoDetailIndex].Duration.ToString(@"hh\:mm");

                    // indicate the state of video playback..
                    if (Videos[VideoDetailIndex].VideoPlaybackState == VideoPlaybackState.New)
                    {
                        // the video has never been played..
                        pbPlayBackState.Image = ImagePlaybackNew;
                    }
                    else if (Videos[VideoDetailIndex].VideoPlaybackState == VideoPlaybackState.Somewhere)
                    {
                        // the video playback was stopped somewhere in the middle..
                        pbPlayBackState.Image = ImagePlaybackMiddle;
                    }
                    else if (Videos[VideoDetailIndex].VideoPlaybackState == VideoPlaybackState.Played)
                    {
                        // the video was played to the end..
                        pbPlayBackState.Image = ImagePlaybackWatched;
                    }
                }
            }
        }
        /// <summary>
        /// A copy method for a TMDbDetail class instance.
        /// </summary>
        /// <param name="detail">A TMDbDetail class instance to construct a TMDbDetailExt class instance.</param>
        /// <param name="duration">A video duration in milliseconds.</param>
        /// <param name="fileNameFull">A full file name for a video this class would represent of.</param>
        /// <param name="imageFileCache">if set to <c>true</c> the class uses file system for caching image files.</param>
        /// <param name="imageFileCacheDir">A full path to use for the image file cache.</param>
        /// <param name="image">A poster/still image which represents the video file. If set to null a web download is tried.</param>
        /// <param name="videoPlaybackState">Indicates the state of how the video was interacted with before.</param>
        /// <returns>A TMDbDetailExt class instance containing the data from the given TMDbDetail class instance.</returns>
        public static TMDbDetailExt FromTMDbDetail(TMDbDetail detail, int duration,
                                                   string fileNameFull, bool imageFileCache, string imageFileCacheDir, Image image, VideoPlaybackState videoPlaybackState)
        {
            // create a new TMDbDetailExt class instance..
            TMDbDetailExt result = new TMDbDetailExt
            {
                // copy the data..
                Description       = detail.Description,
                Episode           = detail.Episode,
                EpisodeID         = detail.EpisodeID,
                DetailDescription = detail.DetailDescription,
                FileName          = detail.FileName,
                ID = detail.ID,
                PosterOrStillURL = detail.PosterOrStillURL,
                Season           = detail.Season,
                SeasonID         = detail.SeasonID,
                Title            = detail.Title
                                   // END: copy the data..
            };

            if (image == null) // if the given image parameter was null try to download the image from the web..
            {
                try
                {
                    // download the image data from the web..
                    using (WebClient webClient = new WebClient())
                    {
                        // download the data as byte array..
                        byte[] imageData = webClient.DownloadData(result.PosterOrStillURL);
                        // using (MemoryStream ms = new MemoryStream(imageData)) Exception: A generic error occurred in GDI+

                        // construct a MemoryStream instance of the downloaded image data..
                        MemoryStream ms = new MemoryStream(imageData);

                        // set the image..
                        result.Image = Image.FromStream(ms);
                    }
                }
                catch
                {
                }
            }
            else // an image was given..
            {
                result.Image = image; // ..so set the image..
            }

            // if there is no TMDb ID for the video and the given image was null the image will be null..
            if (detail.ID == -1 && image == null)
            {
                result.Image = null;
            }

            // set the previous playback state of the video..
            result.VideoPlaybackState = videoPlaybackState;

            // set the duration..
            result.Duration = TimeSpan.FromMilliseconds(duration);

            try // try to set the file size of the video..
            {
                result.FileSize = new FileInfo(fileNameFull).Length;
            }
            catch
            {
                result.FileSize = 0;
            }

            // set the file system caching value..
            result.ImageFileCache = imageFileCache;

            // set the file system cache path..
            result.ImageFileCacheDir = imageFileCacheDir;

            // dump the image to the file system cache path if "conditions" are met..
            result.DumpImage();

            return(result); // return the TMDbDetailExt class instance
        }