예제 #1
0
        /// <summary>
        /// Sync tasks that are currently in the queue.
        /// </summary>
        /// <exception cref="ApiFormatException">if the request times out.</exception>
        /// <remarks>The SyncStart, SyncStop, and SyncError events send error message or success indicators!</remarks>
        public async Task <bool> Sync()
        {
            var remote = await _client.PullAnimeList();

            /*   CASES
             *  0. A queued anime is in neither the remote or the list.
             *      It has likely been manually deleted after a list error.
             *  1. The anime is in remote, but not in list
             *      a. The anime is enqueued for deletion - delete from server
             *      b. The anime is not enqueued for deletion - it was added to the server; add it to the list
             *  2. The anime is in the list, but not in remote
             *      a. The anime is enqueued for addition - add it to the server
             *      b. The anime is not enqueued for addition - it was deleted; remove it from the list
             *  3. The anime is in the list, and in remote.
             *      a. The anime is enqueued for updating - update it on the server and keep our copy.
             *      b. The anime is not enqueued for updating - keep the server's copy; the values could have changed.
             */

            // First lets partition our lists.
            var remoteUnique = remote.Except(_entries).ToList();                            // remote - entries
            var clientUnique = _entries.Except(remote).ToList();                            // entries - remote
            var common       = _entries.Except(remoteUnique).Except(clientUnique).ToList(); // entries u remote

            // Case 0: empty the queue of expired values
            foreach (var e in _queue)
            {
                if (!remote.Contains(e) && !_entries.Contains(e))
                {
                    _queue.Remove(e);
                }
            }

            // Case 1: unique to server
            foreach (var a in remoteUnique)
            {
                if (!_queue.Contains(a))
                {
                    _entries.Add(a);
                }
                else if (_queue.First(x => x.Id == a.Id).ListStatus == ApiEntry.ListStatuses.NotInList)
                {
                    await _client.RemoveAnime(a.Id);

                    _queue.Remove(a);
                }
            }

            // Case 2: unique to client
            foreach (var a in clientUnique)
            {
                if (!_queue.Contains(a))
                {
                    _entries.Remove(a);
                }

                else if (_queue.First(x => x.Id == a.Id).ListStatus != ApiEntry.ListStatuses.NotInList)
                {
                    if (!await _client.AddAnime(a.Id, a.ListStatus))
                    {
                        Debug.WriteLine($"Failed to add {a.Id} {a.Title}");
                    }
                    else if (!await _client.UpdateAnime(a))
                    {
                        Debug.WriteLine($"Failed to update{a.Id} {a.Title}");
                    }
                    else
                    {
                        _queue.Remove(a);
                    }
                }

                else
                {
                    _entries.Remove(a);
                    _queue.Remove(a);
                }
            }

            // Case 3: common to both
            foreach (var a in common)
            {
                if (!_queue.Contains(a))
                {
                    a.Replace(remote.First(x => x.Id == a.Id)); // take the server values
                }
                else if (_queue.First(x => x.Id == a.Id).ListStatus != ApiEntry.ListStatuses.NotInList)
                {
                    if (!await _client.UpdateAnime(a))
                    {
                        Debug.WriteLine($"Failed to update {a.Id} {a.Title}");
                    }
                    else
                    {
                        _queue.Remove(a);
                    }
                }
            }

            if (_queue.Count != 0)
            {
                // Something may have gone wrong here
                Debug.WriteLine("Queue is not empty! Something failed to sync..");
                _queue.ForEach(x => Debug.WriteLine($"{x.Title}, {x.ListStatus}, {x.CurrentEpisode}"));
            }
            else
            {
                Debug.WriteLine("Queue is empty");
            }
            return(_queue.Count == 0);
        }