using Dropbox.Api;
using Dropbox.Api.Files;
using PDF_Office.Model.CloudDrive;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace PDF_Office.ViewModels.HomePanel.CloudDrive.CloudDriveType
{
    /// <summary>
    /// 单用户
    /// </summary>
    public class DropbBoxUserItem : UserBaseItem
    {
        DropboxClient client;
        private List<DropbBoxFiles> FilesList = new List<DropbBoxFiles>();//文件
        private List<Metadata> MetadataList = new List<Metadata>();//文件
        public async Task<bool> LoginUser()
        {
            client = await DropbBoxStatic.Connect();
            if (client == null)
                return false;
            else
                return true;
        }

        public async Task<List<DropbBoxFiles>> RefreshList(string path = "")
        {
            var files = await client.Files.ListFolderAsync(path);
            DropbBoxFiles dropbBoxFiles = new DropbBoxFiles();
            List<DropbBoxFiles> FileList = new List<DropbBoxFiles>();
            foreach (var file in files.Entries)
            {
                dropbBoxFiles.Name = file.Name;
                FileList.Add(dropbBoxFiles);
            }
            MetadataList = (List<Metadata>)files.Entries;
            this.FilesList = FileList;
            return FileList;
        }



        public async Task<string> Download(string name, string savePath)
        {
            Metadata metadata = null;
            foreach(var item in MetadataList)
            {
                if (item.IsFolder)
                    continue;

                if (item.Name == name)
                {
                    metadata = item;
                    break;
                }
            }

            if (metadata != null)
            {
                savePath = savePath + "\\" + metadata.Name;
                using (var response = await client.Files.DownloadAsync(metadata.PathDisplay))
                {
                    var result = await response.GetContentAsStreamAsync();
                    var stream = StreamToMemoryStream(result);
                    using (var fileStream = System.IO.File.Create(savePath))
                    {
                        stream.Seek(0, System.IO.SeekOrigin.Begin);
                        stream.CopyTo(fileStream);
                    }
                }
               // System.Diagnostics.Process.Start(@"explorer.exe", "/select,\"" + savePath + "\"");
                RefreshList(savePath);

                return savePath;
            }
            
            return "";

        }

        public MemoryStream StreamToMemoryStream(Stream stream)
        {
            MemoryStream memoryStream = new MemoryStream();

            //将基础流写入内存流
            const int bufferLength = 1024;
            byte[] buffer = new byte[bufferLength];
            int actual = stream.Read(buffer, 0, bufferLength);
            while (actual > 0)
            {
                // 读、写过程中，流的位置会自动走。
                memoryStream.Write(buffer, 0, actual);
                actual = stream.Read(buffer, 0, bufferLength);
            }
            memoryStream.Position = 0;

            return memoryStream;
        }

        private void Upload()
        {
            //if (ItemList.SelectedItem != null)
            //{
            //    var item = ItemList.SelectedItem as Metadata;
            //    if (item.IsFolder)
            //        return;

            //OpenFileDialog openFileDialog = new OpenFileDialog();
            //if ((bool)openFileDialog.ShowDialog())
            //{
            //    string folder = currentFolder; /*= item.PathDisplay.Replace("/" + item.Name, "");*/
            //    using (var stream = System.IO.File.OpenRead(openFileDialog.FileName))
            //    {
            //        await client.Files.UploadAsync(folder + "/" + openFileDialog.SafeFileName, WriteMode.Overwrite.Instance, body: stream);
            //    }
            //    MessageBox.Show("上传完成");
            //    RefreshList(folder);
            //}
            //}
        }

        private void Loaded()
        {
            //var text = sender as TextBlock;
            //if (text == null)
            //    return;
            //if (text.DataContext is Metadata)
            //{
            //    var data = (text.DataContext as Metadata);
            //    if (data.IsFile)
            //    {
            //        text.Text = "File";
            //    }
            //    if (data.IsFolder)
            //    {
            //        text.Text = "Folder";
            //    }
            //}
        }


    }


    #region 身份验证

    public static class DropbBoxStatic
    {
        // This loopback host is for demo purpose. If this port is not
        // available on your machine you need to update this URL with an unused port.
        public static readonly string LoopbackHost = "http://127.0.0.1:8080/";
        // Add an ApiKey (from https://www.dropbox.com/developers/apps) here
        public static readonly string ApiKey = "k1hv3601odbsmln";
        // URL to receive OAuth 2 redirect from Dropbox server.
        // You also need to register this redirect URL on https://www.dropbox.com/developers/apps.
        public static readonly Uri RedirectUri = new Uri(LoopbackHost + "authorize");

        // URL to receive access token from JS.
        public static readonly Uri JSRedirectUri = new Uri(LoopbackHost + "token");

        private static HttpListener http = new HttpListener();
        public static async Task<DropboxClient> Connect()
        {
            DropboxCertHelper.InitializeCertPinning();
            var state = Guid.NewGuid().ToString("N");
            var OAuthflow = new PKCEOAuthFlow();
            var authorizeUri = OAuthflow.GetAuthorizeUri(OAuthResponseType.Code, ApiKey, RedirectUri.ToString(), state: state, tokenAccessType: TokenAccessType.Offline, scopeList: null, includeGrantedScopes: IncludeGrantedScopes.None);
            //var http = new HttpListener();
            http.Prefixes.Clear();
            http.Prefixes.Add(LoopbackHost);
            http.Start();
            System.Diagnostics.Process.Start(authorizeUri.ToString());

            await HandleOAuth2Redirect(http);

            // Handle redirect from JS and process OAuth response.
            var redirectUri = await HandleJSRedirect(http);

            var tokenResult = await OAuthflow.ProcessCodeFlowAsync(redirectUri, ApiKey, RedirectUri.ToString(), state);

            //  Window.GetWindow(this).Activate();
            DropboxClientConfig dropboxClientConfig = new DropboxClientConfig("ControlTest");

            DropboxClient client;
            client = new DropboxClient(tokenResult.AccessToken, dropboxClientConfig);
            return client;
        }

        /// <summary>
        /// Handle the redirect from JS and process raw redirect URI with fragment to
        /// complete the authorization flow.
        /// </summary>
        /// <param name="http">The http listener.</param>
        /// <returns>The <see cref="OAuth2Response"/></returns>
        private static async Task<Uri> HandleJSRedirect(HttpListener http)
        {
            var context = await http.GetContextAsync();

            // We only care about request to TokenRedirectUri endpoint.
            while (context.Request.Url.AbsolutePath != JSRedirectUri.AbsolutePath)
            {
                context = await http.GetContextAsync();
            }

            var redirectUri = new Uri(context.Request.QueryString["url_with_fragment"]);

            return redirectUri;
        }


        public static void ListenerCallback(IAsyncResult result)
        {
            HttpListener listener = (HttpListener)result.AsyncState;
            // Call EndGetContext to complete the asynchronous operation.
            HttpListenerContext context = listener.EndGetContext(result);
            HttpListenerRequest request = context.Request;
            // Obtain a response object.
            HttpListenerResponse response = context.Response;
            // Construct a response.
            string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();
        }


        /// <summary>
        /// Handles the redirect from Dropbox server. Because we are using token flow, the local
        /// http server cannot directly receive the URL fragment. We need to return a HTML page with
        /// inline JS which can send URL fragment to local server as URL parameter.
        /// </summary>
        /// <param name="http">The http listener.</param>
        /// <returns>The <see cref="Task"/></returns>
        private static async Task HandleOAuth2Redirect(HttpListener http)
        {
            var context = await http.GetContextAsync();

            // We only care about request to RedirectUri endpoint.
            while (context.Request.Url.AbsolutePath != RedirectUri.AbsolutePath)
            {
                context = await http.GetContextAsync();
            }

            context.Response.ContentType = "text/html";

            // Respond with a page which runs JS and sends URL fragment as query string
            // to TokenRedirectUri.
            using (var file = System.IO.File.OpenRead("index.html"))
            {
                file.CopyTo(context.Response.OutputStream);
            }

            context.Response.OutputStream.Close();
        }


    }


    #endregion



}
