﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Ugc.Model;

namespace Unity.Ugc.File
{
    internal class FileManager
    {
        /// <summary>
        /// 同步文件
        /// </summary>
        /// <param name="modId">模组ID</param>
        /// <param name="localFiles">本地要上传的文件</param>
        /// <returns>上传失败的文件列表</returns>
        protected internal static async Task<List<LocalFile>> SyncFiles(string modId, Dictionary<string, LocalFile> localFiles)
        {
            var remoteEntries = await GetRemoteEntries(modId);

            List<LocalFile> toCreate = new List<LocalFile>();
            Dictionary<string, LocalFile> toUpdate = new Dictionary<string, LocalFile>();
            List<string> toDelete = new List<string>();
            
            var failed = new List<LocalFile>();
            
            foreach (ModEntry entry in remoteEntries)
            {
                if (localFiles.TryGetValue(entry.Path, out var localFile))
                {
                    toUpdate.Add(entry.Id, localFile);
                    localFiles.Remove(entry.Path);
                }
                else
                {
                    toDelete.Add(entry.Id);
                }
            }
            
            foreach (KeyValuePair<string, LocalFile> kvp in localFiles)
            {
                toCreate.Add(kvp.Value);
            }

            foreach (var localFile in toCreate)
            {
                var res = await UploadFile(modId, localFile);
                if (!String.IsNullOrEmpty(res))
                {
                    await UgcSDK.CreateEntry(modId, localFile.ToEntryModel());
                }
                else
                {
                    failed.Add(localFile);
                }
            }
            
            foreach (KeyValuePair<string, LocalFile> kvp in toUpdate)
            {
                var res = await UploadFile(modId, kvp.Value);
                if (!String.IsNullOrEmpty(res))
                {
                    await UgcSDK.UpdateEntry(modId, kvp.Key, kvp.Value.ToEntryModel());
                }
                else
                {
                    failed.Add(kvp.Value);
                }
            }
            
            foreach (var entryId in toDelete)
            {
                await UgcSDK.DeleteEntry(modId, entryId);
            }
            
            return failed;
        }

        private static async Task<List<ModEntry>> GetRemoteEntries(string modId)
        {
            var remoteEntries = new List<ModEntry>();
            var currentPage = 1;
            var perPage = 1000;

            while (true)
            {
                var resp = await UgcSDK.ListEntries(modId, currentPage, perPage);
                foreach (var mod in resp.Items)
                {
                    remoteEntries.Add(mod);
                }
                
                if (resp.Pagination.End >= resp.Pagination.Total)
                {
                    break;
                }
                currentPage += 1;
            }

            return remoteEntries;
        } 
        
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="modId">模组的ID</param>
        /// <param name="file">要上传的文件</param>
        /// <returns>文件的url</returns>
        protected internal static async Task<string> UploadFile(string modId, LocalFile file)
        {
            var token = await UgcSDK.GetUploadToken(modId, file.Hash);
            var key = $"{UgcSettings.Instance.uosAppId}/{file.Hash}";
            
            FileUploader.UploadFile(file.Data, file.ContentType, token.Token, key);
            return key;
        }
    }
}