using System.Linq;
using SimpleHttp;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
using TessesYoutubeDownloader.Server.Models;
using Newtonsoft.Json;

namespace youtube_downloader
{
    
    class Program
    {
      
        static void Main(string[] arg)
        {
           
            Thread t = new Thread(new ThreadStart(() => { 
                Server.Functions.Downloader.DL.DownloadThread().GetAwaiter().GetResult();
            }));
            t.Start();
            Thread t2 = new Thread(new ThreadStart(() => {
                Server.Functions.Downloader.DL.ListenForQueueItem().GetAwaiter().GetResult();
            }));
            t2.Start();
            // we need to get our app name so that 
            // we can create unique names for our mutex and our pipe
            string webSitePath = Server.Functions.Downloader.DL.GetPath(true, "WebSite");
            Route.Add("/", (rq, rp,args) =>
            {
                rp.AsFile(rq, Path.Combine(webSitePath, "index.html"));
            });
            Route.Add("/api/Search/{text}", (rq, rp, args) =>
            {
                string search=System.Web.HttpUtility.UrlDecode(args["text"]);
                string json = JsonConvert.SerializeObject(Server.Functions.Downloader.Search(search));
                rp.AsText(json, "application/json");

            });
            Route.Add("/api/Storage/GetDirectories/{Path}", (rq, rp, args) =>
            {
                string path = Server.Functions.Downloader.DL.GetPath(true, args["Path"]);

                if (Directory.Exists(path))
                {
                    string json = Newtonsoft.Json.JsonConvert.SerializeObject(Directory.EnumerateDirectories(path).Select<string, string>((o) => { return Path.GetFileName(o); }));
                    rp.AsText(json, "application/json");
                }
                else
                {
                    rp.AsText("[]", "application/json");
                }
            });
            Route.Add("/api/Storage/GetFiles/{Path}", (rq, rp, args) =>
            {
                string path = Server.Functions.Downloader.DL.GetPath(true, args["Path"]);

                if (Directory.Exists(path))
                {
                    string json = Newtonsoft.Json.JsonConvert.SerializeObject(Directory.EnumerateFiles(path).Select<string, string>((o) => { return Path.GetFileName(o); }));
                    rp.AsText(json, "application/json");
                }
                else
                {
                    rp.AsText("[]", "application/json");
                }
            });
           
            Route.Add("/api/Storage/FileExists/{Path}", (rq, rp, args) =>
            {
                string path = Server.Functions.Downloader.DL.GetPath(true, args["Path"]);
                string json = File.Exists(path) ? "true" : "false";
                rp.AsText(json, "text/plain");
                
            });
            Route.Add("/api/Storage/DirectoryExists/{Path}", (rq, rp, args) =>
            {
                string path = Server.Functions.Downloader.DL.GetPath(true, args["Path"]);
                string json = Directory.Exists(path) ? "true" : "false";
                rp.AsText(json, "text/plain");

            });
            Route.Add("/api/Storage/File/{Path}", (rq, rp, args) =>
            {
                string path = Server.Functions.Downloader.DL.GetPath(true, args["Path"]);
                
                rp.AsFile(rq, path);

            });
            Route.Add("/api/AddVideo/{Id}", (rq, rp, args) =>
             {
                 Server.Functions.Downloader.DownloadVideo(System.Web.HttpUtility.UrlDecode(args["Id"]));
                 
                 rp.AsRedirect("/");
             });
            Route.Add("/api/AddVideoRes/{R}/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadVideo(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"]));
                rp.AsRedirect("/");
            });
            Route.Add("/api/AddPlaylist/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadPlaylist(System.Web.HttpUtility.UrlDecode(args["Id"]));

                rp.AsRedirect("/");
            });
            Route.Add("/api/AddPlaylistRes/{R}/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadPlaylist(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"]));
                rp.AsRedirect("/");
            });
            Route.Add("/api/AddChannel/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadChannel(System.Web.HttpUtility.UrlDecode(args["Id"]));

                rp.AsRedirect("/");
            });
            Route.Add("/api/AddChannelRes/{R}/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadChannel(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"]));
                rp.AsRedirect("/");
            });
            Route.Add("/api/AddUser/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadUser(System.Web.HttpUtility.UrlDecode(args["Id"]));

                rp.AsRedirect("/");
            });
            Route.Add("/api/AddChannelOnly/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadChannelOnly(System.Web.HttpUtility.UrlDecode(args["Id"]));

                rp.AsRedirect("/");
            });
            Route.Add("/api/AddUserOnly/{R}/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadUserOnly(System.Web.HttpUtility.UrlDecode(args["Id"]));
                rp.AsRedirect("/");
            });
            Route.Add("/api/AddUserRes/{R}/{Id}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.DownloadUser(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"]));
                rp.AsRedirect("/");
            });
            Route.Add("/api/QueueMove/{From}/{To}", (rq, rp, args) =>
            {
                Server.Functions.Downloader.ModQueue(args["To"],args["From"]);
                rp.AsRedirect("/");
            });
            Route.Add("/api/QueueList", (rq, rp, args) =>
            {
                string json = Server.Functions.Downloader.GetQueue();
                rp.AsText(json, "application/json");
            });
            Route.Add("/api/Progress", (rq, rp, args) =>
            {
                string json = JsonConvert.SerializeObject(Server.Functions.Downloader.GetProgress());
                rp.AsText(json, "application/json");
            });
            Route.Add("/api/Watch/{VideoId}", (rq, rp, args) =>
            {
                var txt = Templating.RenderFile(Path.Combine(webSitePath, "watch_page.thtml"), args); //populate template
                rp.AsText(txt);
            });

            Route.Add("/api/Redownload", (rq, rp, args) =>
            {
                foreach (var item in Directory.GetFiles(Server.Functions.Downloader.DL.GetPath(true, "Info"), "*.json"))
                {
                    string id = System.IO.Path.GetFileNameWithoutExtension(item);
                    Server.Functions.Downloader.DownloadVideo(id, Resolution.NoConvert);
                }
                rp.AsRedirect("/");
            });
            Route.Add("/api/Redownload/{R}", (rq, rp, args) =>
            {
                foreach (var item in Directory.GetFiles(Server.Functions.Downloader.DL.GetPath(true, "Info"), "*.json"))
                {
                    string id = System.IO.Path.GetFileNameWithoutExtension(item);
                    Server.Functions.Downloader.DownloadVideo(id, (Resolution)int.Parse(args["R"]));
                }
                rp.AsRedirect("/");
            });
            Route.Add("/{Path}", (rq, rp, args) =>
            {
                string path = Path.Combine(webSitePath, args["Path"].Split(new char[] { '?' },StringSplitOptions.RemoveEmptyEntries)[0]);

                rp.AsFile(rq, path);
            });
            if (arg.Length > 0)
            {
                HttpServer.ListenAsync(arg[0], CancellationToken.None, Route.OnHttpRequestAsync).Wait();

            }
            else
            {
                HttpServer.ListenAsync(3250, CancellationToken.None, Route.OnHttpRequestAsync).Wait();
            }
        }
     

       
    }
}
