using C1.Xaml.PdfViewer;
using ControlExplorer;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace ControlExplorer.Controls.PdfViewer
{
    public sealed partial class DemoSavePDF : UserControl, IExposeApplicationBarItems, IFileOpenPickerContinuable, IFileSavePickerContinuable, IWebAuthenticationContinuable
    {
        AppBarButton btnOpen = new AppBarButton { Icon = new SymbolIcon(Symbol.OpenFile) };
        AppBarButton btnSave = new AppBarButton { Icon = new SymbolIcon(Symbol.Save) };
        private CancellationTokenSource _cancellationToken;
        private OneDriveHelper _helper = new OneDriveHelper();
        private string _accessToken;

        public DemoSavePDF()
        {
            this.InitializeComponent();
            btnOpen.Click += btnOpen_Click;
            btnOpen.Label = "Open";
            btnSave.Click += btnSave_Click;
            btnSave.Label = "Save As..";
            this.Loaded += DemoPDFViewer_Loaded;
        }

        void btnSave_Click(object sender, RoutedEventArgs e)
        {
            SavePanel.Visibility = Visibility.Visible;
        }

        void btnOpen_Click(object sender, RoutedEventArgs e)
        {
            FileOpenPicker openPicker = new FileOpenPicker();
            openPicker.ViewMode = PickerViewMode.Thumbnail;
            openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            openPicker.FileTypeFilter.Add(".pdf");

            // Launch file open picker and caller app is suspended and may be terminated if required
            openPicker.PickSingleFileAndContinue();
        }



        private async void DemoPDFViewer_Loaded(object sender, RoutedEventArgs e)
        {
            var resource = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Resources/Pdfs/Presentation.pdf"));
            pdfViewer.LoadDocument(await resource.OpenStreamForReadAsync());
            txtLoading.Visibility = Visibility.Collapsed;
        }

        public IEnumerable<ICommandBarElement> ApplicationBarItems
        {
            get
            {
                yield return btnOpen;
                yield return btnSave;
            }
        }

        public async void ContinueFileOpenPicker(Windows.ApplicationModel.Activation.FileOpenPickerContinuationEventArgs args)
        {
            if (args.Files.Count > 0)
            {
                pdfViewer.LoadDocument(await args.Files[0].OpenStreamForReadAsync());
            }
        }

        public async void ContinueFileSavePicker(Windows.ApplicationModel.Activation.FileSavePickerContinuationEventArgs args)
        {
            StorageFile file = args.File;
            if (file != null)
            {
                var dest = await file.OpenAsync(FileAccessMode.ReadWrite);
                var destStream = dest.AsStream();
                await pdfViewer.SaveDocumentAsync(destStream);
                destStream.Dispose();
                destStream = null;
            }

        }

        public async Task UploadPDFToOneDrive(string fileName)
        {
            if (await Authenticate())
            {
                var prog = StatusBar.GetForCurrentView().ProgressIndicator;
                try
                {
                    var picker = new OneDriveFolderPicker(_accessToken);
                    var folder = await picker.PickFolderAsync(this);
                    //prog.ProgressValue = null;
                    //prog.Text = "Creating document...";
                    await prog.ShowAsync();

                    
                    //// save document
                    prog.Text = "Uploading file to OneDrive...";
                    var stream = new MemoryStream();
                    await pdfViewer.SaveDocumentAsync(stream);
                    stream.Flush();
                    stream.Seek(0, SeekOrigin.Begin);

                    var contentType = "application/pdf";
                    _cancellationToken = new CancellationTokenSource();
                    var file = await OneDriveHelper.UploadFileAsync(_accessToken, fileName + ".pdf", contentType, folder, stream.AsInputStream(), percentage =>
                    {
                        prog.ProgressValue = percentage;
                    }, _cancellationToken.Token);

                    // Open Web browser task to see the file
                    prog.Text = "Getting file link...";
                    prog.ProgressValue = null;
                    var link = await OneDriveHelper.GetFileInfoAsync(_accessToken, file.Id);
                    await prog.HideAsync();
                    await Launcher.LaunchUriAsync(new Uri(link.Link, UriKind.Absolute));
                }
                catch (OperationCanceledException)
                {
                    prog.HideAsync();
                    return;
                }
                catch
                {
                    prog.HideAsync();
                    var dialog = new MessageDialog("There was an error trying to upload the file to OneDrive. Please try again.");
                    dialog.ShowAsync();
                }
            }
        }

        public void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)
        {
            _helper.ContinueAuthentication(args);
        }

        private async Task<bool> Authenticate()
        {
            if (_accessToken == null)
            {
                _helper = new OneDriveHelper();
                try
                {
                    _accessToken = await _helper.GetAccessTokenAsync();
                    return true;
                }
                catch (OperationCanceledException) { }
                catch
                {
                    var dialog = new MessageDialog("You could not get an access token, please check your internet connection.");
                    dialog.ShowAsync();
                }
                return false;
            }
            else
            {
                return true;
            }
        }


        private Task ShowDialog(string msg, string title, List<IUICommand> commands)
        {
            CoreDispatcher dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
            Func<object, Task<bool>> action = null;
            action = async (o) =>
            {
                try
                {
                    if (dispatcher.HasThreadAccess)
                    {
                        MessageDialog dialog = new MessageDialog(msg, title);
                        if (commands != null)
                        {
                            foreach (IUICommand com in commands)
                            {
                                dialog.Commands.Add(com);
                            }
                        }
                        await dialog.ShowAsync();
                    }
                    else
                    {
                        dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                        () => action(o));
                    }
                    return true;
                }
                catch (UnauthorizedAccessException)
                {
                    if (action != null)
                    {
                        Task.Delay(500).ContinueWith(async t => await action(o));
                    }
                }
                return false;
            };
            return action(null);
        }


        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            SavePanel.Visibility = Visibility.Collapsed;  
        }

        private async void OneDriveButton_Click(object sender, RoutedEventArgs e)
        {
            await UploadPDFToOneDrive(txtFileName.Text);
        }

        private void LocalButton_Click(object sender, RoutedEventArgs e)
        {
            FileSavePicker picker = new FileSavePicker();
            picker.FileTypeChoices.Add("PDF", new List<string>() { ".pdf" });
            picker.DefaultFileExtension = ".pdf";
            picker.SuggestedFileName = txtFileName.Text;
            picker.PickSaveFileAndContinue();
        }

        
      
    }
}
