using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TessesYoutubeDownloader.Server.Models;
using YoutubeExplode.Channels;
using YoutubeExplode.Playlists;
using YoutubeExplode.Videos;

namespace youtube_downloader.Server.Models
{
    public class InfomationQueueItem
    {
        public InfomationQueueItem(VideoId id,Resolution res,bool download = true)
        {
            Data = id.Value;
            DownloadActualDataAfterwards = download;
            Type = InfoType.Video;
            this.res = res;
        }
        public InfomationQueueItem(PlaylistId id,Resolution res,bool download = true)
        {
            Data = id.Value;
            DownloadActualDataAfterwards = download;
            Type = InfoType.Playlist;
            this.res = res;
        }
        public InfomationQueueItem(ChannelId id, Resolution res, bool download = true)
        {
            Data = id.Value;
            DownloadActualDataAfterwards = download;
            Type = InfoType.Channel;
            this.res = res;
        }
        public InfomationQueueItem(UserName id, Resolution res, bool download = true)
        {
            Data = id.Value;
            DownloadActualDataAfterwards = download;
            Type = InfoType.User;
            this.res = res;
        }
        Resolution res;
        /// <summary>
        /// Download it afterwards
        /// </summary>
        public bool DownloadActualDataAfterwards { get; set; }
        /// <summary>
        /// Kind
        /// </summary>
        public InfoType Type { get; set; }
        /// <summary>
        /// ID for item
        /// </summary>
        public string Data { get; set; }

        public async Task<SavedVideoObject[]> DownloadData()
        {
            switch (Type)
            {
                case InfoType.Video:
                    { 
                        string infPath = Functions.Downloader.DL.GetPath(true, "Info", Data + ".json");
                        SavedVideoObject sv;
                        bool exist = File.Exists(infPath);
                        if (exist)
                        {
                            sv = new SavedVideoObject();
                            sv.Resolution = res;
                            sv.Video = JsonConvert.DeserializeObject<SavedVideo>(File.ReadAllText(infPath));
                        }
                        else
                        {
                            var vinfo = await Functions.Downloader.DL.ytc.Videos.GetAsync(Data);


                            sv = SavedVideo.CreateFrom(res, vinfo, Functions.Downloader.DL._DownloadThumbnail);

                        }

                        if (!exist)
                        {
                            File.WriteAllText(infPath, JsonConvert.SerializeObject(sv.Video));
                        }
                        return new SavedVideoObject[] { sv };
                     }
                case InfoType.Playlist:
                    { List<SavedVideoObject> video2 = new List<SavedVideoObject>();
                       
                        List<string> vo = new List<string>();
                        SavedPlaylist pl = await SavedPlaylist.FromPlaylistId(res, Functions.Downloader.DL.ytc, Data, (e,f) => { vo.Add(e); }, Functions.Downloader.DL._DownloadThumbnail);
                        string infpath = Functions.Downloader.DL.GetPath(true, "Playlist", Data + ".json");
                        File.WriteAllText(infpath, JsonConvert.SerializeObject(pl));
                        foreach(var str in vo)
                        {
                            string infPath = Functions.Downloader.DL.GetPath(true, "Info", str + ".json");
                            SavedVideoObject sv;
                            bool exist = File.Exists(infPath);
                            if (exist)
                            {
                                sv = new SavedVideoObject();
                                sv.Resolution = res;
                                sv.Video = JsonConvert.DeserializeObject<SavedVideo>(File.ReadAllText(infPath));
                            }
                            else
                            {
                                try
                                {
                                    var vinfo = await Functions.Downloader.DL.ytc.Videos.GetAsync(str);


                                    sv = SavedVideo.CreateFrom(res, vinfo, Functions.Downloader.DL._DownloadThumbnail);
                                }catch(Exception ex)
                                {
                                    Console.WriteLine(ex.Message);

                                    sv = null;
                                    _ = ex;
                                }
                            }

                            if (!exist)
                            {
                                File.WriteAllText(infPath, JsonConvert.SerializeObject(sv.Video));
                            }
                            if(sv != null)
                            {
                                video2.Add(sv);
                            }
                        }
                        return video2.ToArray();

                    }
                case InfoType.Channel:
                    {
                        List<SavedVideoObject> video = new List<SavedVideoObject>();
                        try
                        {
                            var c = Functions.Downloader.DL.ytc.Channels.GetAsync(Data).GetAwaiter().GetResult();
                            SavedChannel c2 = SavedChannel.FromChannel(c, Functions.Downloader.DL._DownloadThumbnail);
                            string infpath = Functions.Downloader.DL.GetPath(true, "Channel", Data + ".json");
                            File.WriteAllText(infpath, JsonConvert.SerializeObject(c2));

                            try
                            {
                                Functions.Downloader.DL.ytc.Channels.GetUploadsAsync(c.Id).ForEachAsync(async (v) =>
                                {
                                    string infPath = Functions.Downloader.DL.GetPath(true, "Info", v.Id + ".json");
                                  
                                    bool exist = File.Exists(infPath);
                                    if (exist)
                                    {
                                       SavedVideoObject sv = new SavedVideoObject();
                                        sv.Resolution = res;
                                        sv.Video = JsonConvert.DeserializeObject<SavedVideo>(File.ReadAllText(infPath));
                                        video.Add(sv);
                                    }
                                    else
                                    {
                                        try
                                        {
                                            var vinfo = await Functions.Downloader.DL.ytc.Videos.GetAsync(v.Id);


                                          SavedVideoObject  sv = SavedVideo.CreateFrom(res, vinfo, Functions.Downloader.DL._DownloadThumbnail);
                                            video.Add(sv);
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.WriteLine(ex.Message);

                                            _ = ex;
                                        }
                                    }
                                }).Wait();
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);

                                _ = ex;
                            }
                        }
                        catch (Exception ex2)
                        {
                            Console.WriteLine(ex2.Message);

                            _ = ex2;
                        }
                        return video.ToArray();
                    }
                case InfoType.User:
                    {
                        List<SavedVideoObject> video = new List<SavedVideoObject>();
                        try
                        {
                            var c = Functions.Downloader.DL.ytc.Channels.GetByUserAsync(Data).GetAwaiter().GetResult();
                            SavedChannel c2 = SavedChannel.FromChannel(c, Functions.Downloader.DL._DownloadThumbnail);
                            string infpath = Functions.Downloader.DL.GetPath(true, "Channel", Data + ".json");
                            File.WriteAllText(infpath, JsonConvert.SerializeObject(c2));

                            try
                            {
                                Functions.Downloader.DL.ytc.Channels.GetUploadsAsync(c.Id).ForEachAsync(async (v) =>
                                {
                                    string infPath = Functions.Downloader.DL.GetPath(true, "Info", v.Id + ".json");

                                    bool exist = File.Exists(infPath);
                                    if (exist)
                                    {
                                        SavedVideoObject sv = new SavedVideoObject();
                                        sv.Resolution = res;
                                        sv.Video = JsonConvert.DeserializeObject<SavedVideo>(File.ReadAllText(infPath));
                                        video.Add(sv);
                                    }
                                    else
                                    {
                                        try
                                        {
                                            var vinfo = await Functions.Downloader.DL.ytc.Videos.GetAsync(v.Id);


                                            SavedVideoObject sv = SavedVideo.CreateFrom(res, vinfo, Functions.Downloader.DL._DownloadThumbnail);
                                            video.Add(sv);
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.WriteLine(ex.Message);


                                            _ = ex;
                                        }
                                    }
                                }).Wait();
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);

                                _ = ex;
                            }
                        }
                        catch (Exception ex2)
                        {
                            Console.WriteLine(ex2.Message);

                            _ = ex2;
                        }
                        return video.ToArray();
                    }
            }
            return new SavedVideoObject[0];
        }
    }
}
