public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
        {
            var liveTvItem = item as LiveTvProgram;

            if (liveTvItem != null)
            {
                return !liveTvItem.HasImage(ImageType.Primary);
            }
            return false;
        }
        public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
        {
            var channelItem = item as IChannelItem;

            if (channelItem != null)
            {
                return !channelItem.HasImage(ImageType.Primary) && !string.IsNullOrWhiteSpace(channelItem.OriginalImageUrl);
            }
            return false;
        }
 public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
 {
     return GetSupportedImages(item).Any(i => !item.HasImage(i));
 }
        public async Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken)
        {
            if (status == null)
            {
                throw new ArgumentNullException("status");
            }

            cancellationToken.ThrowIfCancellationRequested();

            await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);

            IDbTransaction transaction = null;

            try
            {
                transaction = _connection.BeginTransaction();
                
                _saveStatusCommand.GetParameter(0).Value = status.ItemId;
                _saveStatusCommand.GetParameter(1).Value = status.DateLastMetadataRefresh;
                _saveStatusCommand.GetParameter(2).Value = status.DateLastImagesRefresh;
                _saveStatusCommand.GetParameter(3).Value = status.ItemDateModified;

                _saveStatusCommand.Transaction = transaction;

                _saveStatusCommand.ExecuteNonQuery();

                transaction.Commit();
            }
            catch (OperationCanceledException)
            {
                if (transaction != null)
                {
                    transaction.Rollback();
                }

                throw;
            }
            catch (Exception e)
            {
                Logger.ErrorException("Failed to save provider info:", e);

                if (transaction != null)
                {
                    transaction.Rollback();
                }

                throw;
            }
            finally
            {
                if (transaction != null)
                {
                    transaction.Dispose();
                }

                WriteLock.Release();
            }
        }
        private MetadataStatus GetStatus(IDataReader reader)
        {
            var result = new MetadataStatus
            {
                ItemId = reader.GetGuid(0)
            };

            if (!reader.IsDBNull(1))
            {
                result.DateLastMetadataRefresh = reader.GetDateTime(1).ToUniversalTime();
            }

            if (!reader.IsDBNull(2))
            {
                result.DateLastImagesRefresh = reader.GetDateTime(2).ToUniversalTime();
            }

            if (!reader.IsDBNull(3))
            {
                result.ItemDateModified = reader.GetDateTime(3).ToUniversalTime();
            }

            return result;
        }
        public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
        {
            var liveTvItem = item as ILiveTvRecording;

            if (liveTvItem != null)
            {
                return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.RecordingInfo.HasImage ?? true);
            }
            return false;
        }
        public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
        {
            if (status.ItemDateModified.HasValue)
            {
                if (status.ItemDateModified.Value != item.DateModified)
                {
                    return true;
                }
            }

            return false;
        }
        public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
        {
            if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates)
            {
                return false;
            }

            var tvdbId = item.GetProviderId(MetadataProviders.Tvdb);

            if (!String.IsNullOrEmpty(tvdbId))
            {
                // Process images
                var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId), "banners.xml");

                var fileInfo = new FileInfo(imagesXmlPath);

                return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > (status.DateLastMetadataRefresh ?? DateTime.MinValue);
            }

            return false;
        }
        public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
        {
            var liveTvItem = item as LiveTvChannel;

            if (liveTvItem != null)
            {
                return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.HasProviderImage ?? true);
            }
            return false;
        }
        private MetadataStatus GetStatus(IDataReader reader)
        {
            var result = new MetadataStatus
            {
                ItemId = reader.GetGuid(0)
            };

            if (!reader.IsDBNull(1))
            {
                result.ItemName = reader.GetString(1);
            }

            if (!reader.IsDBNull(2))
            {
                result.ItemName = reader.GetString(2);
            }

            if (!reader.IsDBNull(3))
            {
                result.SeriesName = reader.GetString(3);
            }

            if (!reader.IsDBNull(4))
            {
                result.DateLastMetadataRefresh = reader.GetDateTime(4).ToUniversalTime();
            }

            if (!reader.IsDBNull(5))
            {
                result.DateLastImagesRefresh = reader.GetDateTime(5).ToUniversalTime();
            }

            if (!reader.IsDBNull(6))
            {
                result.LastErrorMessage = reader.GetString(6);
            }

            if (!reader.IsDBNull(7))
            {
                result.ItemDateModified = reader.GetDateTime(7).ToUniversalTime();
            }

            return result;
        }
        public async Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken)
        {
            if (status == null)
            {
                throw new ArgumentNullException("status");
            }

            cancellationToken.ThrowIfCancellationRequested();

            await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);

            IDbTransaction transaction = null;

            try
            {
                transaction = _connection.BeginTransaction();
                
                _saveStatusCommand.GetParameter(0).Value = status.ItemId;
                _saveStatusCommand.GetParameter(1).Value = status.ItemName;
                _saveStatusCommand.GetParameter(2).Value = status.ItemType;
                _saveStatusCommand.GetParameter(3).Value = status.SeriesName;
                _saveStatusCommand.GetParameter(4).Value = status.DateLastMetadataRefresh;
                _saveStatusCommand.GetParameter(5).Value = status.DateLastImagesRefresh;
                _saveStatusCommand.GetParameter(6).Value = status.LastStatus.ToString();
                _saveStatusCommand.GetParameter(7).Value = status.LastErrorMessage;
                _saveStatusCommand.GetParameter(8).Value = string.Join("|", status.MetadataProvidersRefreshed.ToArray());
                _saveStatusCommand.GetParameter(9).Value = string.Join("|", status.ImageProvidersRefreshed.ToArray());

                _saveStatusCommand.Transaction = transaction;

                _saveStatusCommand.ExecuteNonQuery();

                transaction.Commit();
            }
            catch (OperationCanceledException)
            {
                if (transaction != null)
                {
                    transaction.Rollback();
                }

                throw;
            }
            catch (Exception e)
            {
                _logger.ErrorException("Failed to save provider info:", e);

                if (transaction != null)
                {
                    transaction.Rollback();
                }

                throw;
            }
            finally
            {
                if (transaction != null)
                {
                    transaction.Dispose();
                }

                _writeLock.Release();
            }
        }
        private MetadataStatus GetStatus(IDataReader reader)
        {
            var result = new MetadataStatus
            {
                ItemId = reader.GetGuid(0)
            };

            if (!reader.IsDBNull(1))
            {
                result.ItemName = reader.GetString(1);
            }

            if (!reader.IsDBNull(2))
            {
                result.ItemName = reader.GetString(2);
            }

            if (!reader.IsDBNull(3))
            {
                result.SeriesName = reader.GetString(3);
            }

            if (!reader.IsDBNull(4))
            {
                result.DateLastMetadataRefresh = reader.GetDateTime(4).ToUniversalTime();
            }

            if (!reader.IsDBNull(5))
            {
                result.DateLastImagesRefresh = reader.GetDateTime(5).ToUniversalTime();
            }

            if (!reader.IsDBNull(6))
            {
                result.LastStatus = (ProviderRefreshStatus)Enum.Parse(typeof(ProviderRefreshStatus), reader.GetString(6), true);
            }

            if (!reader.IsDBNull(7))
            {
                result.LastErrorMessage = reader.GetString(7);
            }

            if (!reader.IsDBNull(8))
            {
                result.MetadataProvidersRefreshed = reader.GetString(8).Split('|').Where(i => !string.IsNullOrEmpty(i)).Select(i => new Guid(i)).ToList();
            }

            if (!reader.IsDBNull(9))
            {
                result.ImageProvidersRefreshed = reader.GetString(9).Split('|').Where(i => !string.IsNullOrEmpty(i)).Select(i => new Guid(i)).ToList();
            }

            return result;
        }
        public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
        {
            var liveTvItem = item as ILiveTvRecording;

            if (liveTvItem != null)
            {
                return !liveTvItem.HasImage(ImageType.Primary) && (!string.IsNullOrWhiteSpace(liveTvItem.ProviderImagePath) || !string.IsNullOrWhiteSpace(liveTvItem.ProviderImageUrl));
            }
            return false;
        }