// Decompiled with JetBrains decompiler
// Type: ZuneUI.LibraryPlaybackTrack
// Assembly: ZuneShell, Version=4.7.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
// MVID: FC8028F3-A47B-4FB4-B35B-11D1752D8264
// Assembly location: C:\Program Files\Zune\ZuneShell.dll

using Microsoft.Iris;
using Microsoft.Zune.Playlist;
using Microsoft.Zune.Shell;
using Microsoft.Zune.Util;
using MicrosoftZuneLibrary;
using MicrosoftZunePlayback;
using System;
using System.Threading;

namespace ZuneUI
{
    [Serializable]
    public class LibraryPlaybackTrack : PlaybackTrack
    {
        private const long c_bookmarkInterval = 10000000;
        private int _mediaId;
        private Guid _zuneMediaInstanceId;
        private Guid? _zuneMediaId;
        private MediaType _mediaType;
        private EListType _listType;
        private Streaming _isStreaming;
        private bool _isInCollection;
        private bool? _isVideo;
        private int? _userRating;
        private long _markPlayedAt;
        private bool _hasMarkedPlayed;
        private bool _hasIncrementedPlayCount;
        private bool _hasIncrementedSkipCount;
        private long _lastStoredBookmark;
        private long _duration;
        private static long[] c_podcastVideoLengths = new long[3]
        {
            0L,
            3000000000L,
            6000000000L
        };
        private static long[] c_podcastVideoMarkPlayedAtEOFMinus = new long[3]
        {
            300000000L,
            600000000L,
            1200000000L
        };

        public LibraryPlaybackTrack(int mediaId, MediaType mediaType, ContainerPlayMarker containerPlayMarker)
        {
            this._mediaId = mediaId;
            this._mediaType = mediaType;
            this._listType = PlaylistManager.MediaTypeToListType(mediaType);
            this._containerPlayMarker = containerPlayMarker;
            ThreadPool.QueueUserWorkItem(args =>
            {
                this._isInCollection = PlaylistManager.IsInCollection(this._mediaId, this._mediaType);
                Application.DeferredInvoke(delegate
                {
                    this.RatingChanged.Invoke();
                }, null);
            }, null);
        }

        public int MediaId => this._mediaId;

        public override Guid ZuneMediaInstanceId => this._zuneMediaInstanceId;

        public override MediaType MediaType => this._mediaType;

        public EListType ListType => this._listType;

        public override bool IsVideo
        {
            get
            {
                if (!this._isVideo.HasValue)
                    this._isVideo = new bool?(PlaylistManager.IsVideo(this._mediaId, this._mediaType));
                return this._isVideo.Value;
            }
        }

        public override bool IsMusic => this._mediaType == MediaType.Track;

        public override bool IsHD => this.IsVideo && VideoDefinitionHelper.IsHD((VideoDefinition)PlaylistManager.GetFieldValue(this._mediaId, this._listType, 440, -1));

        public override bool IsStreaming
        {
            get
            {
                if (this._isStreaming == Streaming.Unknown)
                    this._isStreaming = PlaylistManager.GetFieldValue(this._mediaId, this._listType, 177, -1) == 43 ? Streaming.Yes : Streaming.No;
                return this._isStreaming == Streaming.Yes;
            }
        }

        public override Guid ZuneMediaId
        {
            get
            {
                if (!this._zuneMediaId.HasValue)
                    this._zuneMediaId = new Guid?(PlaylistManager.GetFieldValue(this._mediaId, this._listType, 451, Guid.Empty));
                return this._zuneMediaId.Value;
            }
        }

        public override string Title => PlaylistManager.GetFieldValue(this._mediaId, this._listType, 344, string.Empty);

        public override TimeSpan Duration => PlaylistManager.GetFieldValue(this._mediaId, this._listType, 151, TimeSpan.Zero);

        public int AlbumLibraryId => PlaylistManager.GetFieldValue(this._mediaId, this._listType, 11, -1);

        public int AlbumArtistLibraryId
        {
            get
            {
                int albumLibraryId = this.AlbumLibraryId;
                return albumLibraryId >= 0 ? PlaylistManager.GetFieldValue(albumLibraryId, EListType.eAlbumList, 78, -1) : -1;
            }
        }

        public override bool CanRate
        {
            get
            {
                bool flag1 = this._containerPlayMarker != null && this._containerPlayMarker.PlaylistType == PlaylistType.QuickMix;
                bool flag2 = false;
                if (this.MediaType == MediaType.Track)
                    flag2 = flag1 || this.IsInCollection;
                return flag2;
            }
        }

        public override int UserRating
        {
            get
            {
                if (!this.CanRate)
                    return 0;
                if (!this._userRating.HasValue)
                    this._userRating = new int?(PlaylistManager.GetFieldValue(this._mediaId, this._listType, 372, 0));
                return this._userRating.Value;
            }
            set
            {
                if (!this.CanRate)
                    return;
                this._userRating = new int?(value);
                PlaylistManager.SetFieldValue(this._mediaId, this._listType, 372, value);
                this.RatingChanged.Invoke();
            }
        }

        public override bool IsInCollection => this._isInCollection;

        public override bool IsInVisibleCollection => PlaylistManager.IsInVisibleCollection(this._mediaId, this._mediaType);

        private long Bookmark => this._mediaType == MediaType.PodcastEpisode || this._mediaType == MediaType.Video ? PlaylistManager.GetFieldValue(this._mediaId, this._listType, 35, 0L) : 0L;

        private string Album => PlaylistManager.GetFieldValue(this._mediaId, this._listType, this._mediaType == MediaType.PodcastEpisode ? 312 : 382, string.Empty);

        public string DisplayArtist => PlaylistManager.GetFieldValue(this._mediaId, this._listType, this._mediaType == MediaType.PodcastEpisode ? 24 : 138, string.Empty);

        public override string ServiceContext
        {
            get
            {
                int num = 0;
                if (this.MediaType != MediaType.PodcastEpisode)
                    num = PlaylistManager.GetFieldValue(this._mediaId, this._listType, 358, 0);
                return num != 0 ? num.ToString() : null;
            }
        }

        private int TrackNumber => this._mediaType != MediaType.PodcastEpisode ? PlaylistManager.GetFieldValue(this._mediaId, this._listType, 437, 0) : 0;

        public override HRESULT GetURI(out string uri)
        {
            string uriOut = null;
            HRESULT hresult = HRESULT._S_OK;
            Microsoft.Zune.Service.EContentType eContentType;
            if (PlaylistManager.GetFieldValue(this._mediaId, this._listType, 177, -1) == 43)
            {
                eContentType = Microsoft.Zune.Service.EContentType.Video;
            }
            else
            {
                eContentType = Microsoft.Zune.Service.EContentType.MusicTrack;
                uriOut = PlaylistManager.GetFieldValue(this._mediaId, this._listType, 317, (string)null);
                if (!string.IsNullOrEmpty(uriOut))
                {
                    try
                    {
                        if (new Uri(uriOut).Scheme == Uri.UriSchemeFile)
                        {
                            if (!ZuneLibrary.DoesFileExist(uriOut))
                                uriOut = null;
                        }
                    }
                    catch (UriFormatException ex)
                    {
                    }
                }
            }
            if (string.IsNullOrEmpty(uriOut) && this.ZuneMediaId != Guid.Empty)
                hresult = ZuneApplication.Service.GetContentUri(this.ZuneMediaId, eContentType, Microsoft.Zune.Service.EContentUriFlags.None, out uriOut, out this._zuneMediaInstanceId);
            uri = uriOut;
            return hresult;
        }

        internal override void OnBeginPlayback(PlayerInterop playbackWrapper)
        {
            base.OnBeginPlayback(playbackWrapper);
            this._hasMarkedPlayed = false;
            this._markPlayedAt = 0L;
            this._hasIncrementedPlayCount = false;
            this._hasIncrementedSkipCount = false;
            this._lastStoredBookmark = 0L;
            this._duration = playbackWrapper.Duration;
            if (this._mediaType == ZuneUI.MediaType.PodcastEpisode || this._mediaType == ZuneUI.MediaType.Video)
            {
                PodcastVideoLengthGroup videoLengthGroup = PodcastVideoLengthGroup.Long;
                while (videoLengthGroup > PodcastVideoLengthGroup.Short && this._duration <= c_podcastVideoLengths[(int)videoLengthGroup])
                    --videoLengthGroup;
                this._markPlayedAt = this._duration - c_podcastVideoMarkPlayedAtEOFMinus[(int)videoLengthGroup];
                if (this._markPlayedAt < 1L)
                    this._markPlayedAt = 1L;
                this._lastStoredBookmark = this.Bookmark;
                if (this._lastStoredBookmark != 0L)
                {
                    playbackWrapper.SeekToAbsolutePosition(this._lastStoredBookmark);
                    if (this._lastStoredBookmark > 200000000L)
                        this._hasIncrementedPlayCount = true;
                }
                if (this._mediaType == ZuneUI.MediaType.PodcastEpisode)
                {
                    if (this.IsVideo)
                        SQMLog.Log(SQMDataId.PodcastVideoEpisodePlayed, 1);
                    else
                        SQMLog.Log(SQMDataId.PodcastAudioEpisodePlayed, 1);
                }
            }
            EMediaTypes MediaType;
            switch (this.MediaType)
            {
                case ZuneUI.MediaType.Track:
                    MediaType = EMediaTypes.eMediaTypeAudio;
                    break;
                case ZuneUI.MediaType.Video:
                    MediaType = EMediaTypes.eMediaTypeVideo;
                    break;
                case ZuneUI.MediaType.PodcastEpisode:
                    MediaType = EMediaTypes.eMediaTypePodcastEpisode;
                    break;
                default:
                    MediaType = EMediaTypes.eMediaTypeInvalid;
                    break;
            }
            Microsoft.Zune.Util.Notification.BroadcastNowPlaying(MediaType, this.Album, this.DisplayArtist, this.Title, this.TrackNumber, this.ZuneMediaId);
        }

        internal override void OnPositionChanged(long position)
        {
            bool markPlayed = false;
            bool incrementPlayCount = false;
            if (position <= 0L || position >= this._duration)
                return;
            if (!this._hasMarkedPlayed && this._markPlayedAt > 0L && position >= this._markPlayedAt)
            {
                this._hasMarkedPlayed = true;
                markPlayed = true;
            }
            if (!this._hasIncrementedPlayCount && position >= 200000000L)
            {
                this._hasIncrementedPlayCount = true;
                incrementPlayCount = true;
            }
            long num = 0;
            if (!this._hasMarkedPlayed)
                num = position / 10000000L * 10000000L;
            if (this._lastStoredBookmark != num)
                this._lastStoredBookmark = num;
            if (!markPlayed && !incrementPlayCount)
                return;
            this.UpdatePlayedStates(markPlayed, incrementPlayCount, false);
        }

        internal override void OnSkip()
        {
            if (this._hasIncrementedPlayCount || this._hasIncrementedSkipCount || this.MediaType == MediaType.PodcastEpisode)
                return;
            this._hasIncrementedSkipCount = true;
            this.UpdatePlayedStates(false, false, true);
        }

        internal override void OnEndPlayback(bool endOfMedia)
        {
            base.OnEndPlayback(endOfMedia);
            Microsoft.Zune.Util.Notification.ResetNowPlaying();
            if (endOfMedia)
            {
                this._lastStoredBookmark = 0L;
                if (!this._hasIncrementedPlayCount)
                    this.UpdatePlayedStates(false, true, false);
            }
            this.CommitLastStoredBookmark();
        }

        private void UpdatePlayedStates(
          bool markPlayed,
          bool incrementPlayCount,
          bool incrementSkipCount)
        {
            int mediaId = this.MediaId;
            if (mediaId == -1)
                return;
            EListType listType = this.ListType;
            ContainerPlayMarker containerPlayMarker = this._containerPlayMarker;
            ThreadPool.QueueUserWorkItem(new WaitCallback(UpdatePlayedStatesWorker), new UpdatePlayedStatesTask(markPlayed, incrementPlayCount, incrementSkipCount, mediaId, listType, containerPlayMarker));
            bool flag = this._containerPlayMarker != null && this._containerPlayMarker.PlaylistType == PlaylistType.QuickMix;
            if (incrementPlayCount)
            {
                if (this._mediaType == MediaType.Track)
                    ++Shell.MainFrame.Social.PlayCount;
                if (flag)
                    SQMLog.Log(SQMDataId.QuickMixTrackPlays, 1);
            }
            if (!incrementSkipCount || !flag)
                return;
            if (this.IsInVisibleCollection)
                SQMLog.Log(SQMDataId.QuickMixLocalSkips, 1);
            else
                SQMLog.Log(SQMDataId.QuickMixRemoteSkips, 1);
        }

        private static void UpdatePlayedStatesWorker(object o)
        {
            if (!(o is UpdatePlayedStatesTask playedStatesTask))
                return;
            int num1 = 0;
            int num2 = 0;
            int num3 = 0;
            int[] columnIndexes = new int[7];
            object[] fieldValues = new object[7];
            if (playedStatesTask.IncrementPlayCount)
            {
                columnIndexes[0] = 367;
                fieldValues[0] = 0;
                ZuneLibrary.GetFieldValues(playedStatesTask.MediaID, playedStatesTask.ListType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
                num2 = (int)fieldValues[0];
                columnIndexes[0] = 366;
                fieldValues[0] = 0;
                ZuneLibrary.GetFieldValues(playedStatesTask.MediaID, playedStatesTask.ListType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
                num1 = (int)fieldValues[0];
            }
            if (playedStatesTask.IncrementSkipCount)
            {
                columnIndexes[0] = 374;
                fieldValues[0] = 0;
                ZuneLibrary.GetFieldValues(playedStatesTask.MediaID, playedStatesTask.ListType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
                num3 = (int)fieldValues[0];
            }
            int cValues = 0;
            if (playedStatesTask.MarkPlayed)
            {
                columnIndexes[cValues] = 262;
                fieldValues[cValues] = 1;
                ++cValues;
            }
            if (playedStatesTask.IncrementPlayCount)
            {
                int num4 = num2 + 1;
                columnIndexes[cValues] = 367;
                fieldValues[cValues] = num4;
                int index1 = cValues + 1;
                int num5 = num1 + 1;
                columnIndexes[index1] = 366;
                fieldValues[index1] = num5;
                int index2 = index1 + 1;
                columnIndexes[index2] = 363;
                fieldValues[index2] = DateTime.UtcNow;
                cValues = index2 + 1;
            }
            if (playedStatesTask.IncrementSkipCount)
            {
                int num4 = num3 + 1;
                columnIndexes[cValues] = 374;
                fieldValues[cValues] = num4;
                int index = cValues + 1;
                columnIndexes[index] = 365;
                fieldValues[index] = DateTime.UtcNow;
                cValues = index + 1;
            }
            if (cValues > 0)
                ZuneLibrary.SetFieldValues(playedStatesTask.MediaID, playedStatesTask.ListType, cValues, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
            if (!playedStatesTask.IncrementPlayCount || playedStatesTask.ContainerPlayMarker == null)
                return;
            bool flag = false;
            lock (playedStatesTask.ContainerPlayMarker)
            {
                if (!playedStatesTask.ContainerPlayMarker.Marked)
                {
                    playedStatesTask.ContainerPlayMarker.Marked = true;
                    flag = true;
                }
            }
            if (!flag)
                return;
            if (playedStatesTask.ContainerPlayMarker.LibraryId == -1 && playedStatesTask.ListType == EListType.eTrackList)
            {
                fieldValues[0] = -1;
                if (playedStatesTask.ContainerPlayMarker.MediaType == MediaType.Album)
                {
                    columnIndexes[0] = 11;
                    ZuneLibrary.GetFieldValues(playedStatesTask.MediaID, playedStatesTask.ListType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
                    playedStatesTask.ContainerPlayMarker.LibraryId = (int)fieldValues[0];
                }
                else if (playedStatesTask.ContainerPlayMarker.MediaType == MediaType.Genre)
                {
                    columnIndexes[0] = 399;
                    ZuneLibrary.GetFieldValues(playedStatesTask.MediaID, playedStatesTask.ListType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
                    playedStatesTask.ContainerPlayMarker.LibraryId = (int)fieldValues[0];
                }
                else if (playedStatesTask.ContainerPlayMarker.MediaType == MediaType.Artist)
                {
                    columnIndexes[0] = 11;
                    ZuneLibrary.GetFieldValues(playedStatesTask.MediaID, playedStatesTask.ListType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
                    int iMediaId = (int)fieldValues[0];
                    fieldValues[0] = -1;
                    columnIndexes[0] = 78;
                    ZuneLibrary.GetFieldValues(iMediaId, EListType.eAlbumList, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
                    playedStatesTask.ContainerPlayMarker.LibraryId = (int)fieldValues[0];
                }
            }
            if (playedStatesTask.ContainerPlayMarker.LibraryId == -1)
                return;
            columnIndexes[0] = 363;
            fieldValues[0] = DateTime.UtcNow;
            EListType listType = PlaylistManager.MediaTypeToListType(playedStatesTask.ContainerPlayMarker.MediaType);
            ZuneLibrary.SetFieldValues(playedStatesTask.ContainerPlayMarker.LibraryId, listType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
        }

        private void CommitLastStoredBookmark()
        {
            if (this.MediaType != MediaType.PodcastEpisode && this.MediaType != MediaType.Video)
                return;
            int[] columnIndexes = new int[1];
            object[] fieldValues = new object[1];
            columnIndexes[0] = 35;
            fieldValues[0] = _lastStoredBookmark;
            ZuneLibrary.SetFieldValues(this.MediaId, this.ListType, 1, columnIndexes, fieldValues, PlaylistManager.Instance.QueryContext);
        }

        public void FindInCollection()
        {
            if (this._mediaType != MediaType.Track)
                return;
            MusicLibraryPage.FindInCollection(this.AlbumArtistLibraryId, this.AlbumLibraryId, this.MediaId);
        }

        public void RatingUpdatedExternally(int newRating)
        {
            this._userRating = new int?(newRating);
            this.RatingChanged.Invoke();
        }

        private class UpdatePlayedStatesTask
        {
            public readonly bool MarkPlayed;
            public readonly bool IncrementPlayCount;
            public readonly bool IncrementSkipCount;
            public readonly int MediaID;
            public readonly EListType ListType;
            public readonly ContainerPlayMarker ContainerPlayMarker;

            public UpdatePlayedStatesTask(
              bool markPlayed,
              bool incrementPlayCount,
              bool incrementSkipCount,
              int mediaID,
              EListType listType,
              ContainerPlayMarker containerPlayMarker)
            {
                this.MarkPlayed = markPlayed;
                this.IncrementPlayCount = incrementPlayCount;
                this.IncrementSkipCount = incrementSkipCount;
                this.MediaID = mediaID;
                this.ListType = listType;
                this.ContainerPlayMarker = containerPlayMarker;
            }
        }

        public enum Streaming
        {
            Unknown,
            Yes,
            No,
        }

        private enum PodcastVideoLengthGroup
        {
            Short,
            Medium,
            Long,
        }
    }
}
