using C1.Xaml.Pdf;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.System;
using Windows.UI;
using Windows.UI.Popups;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web.Http;

namespace ControlExplorer.Controls.Pdf
{
    public partial class DemoPdf
        : UserControl, IWebAuthenticationContinuable
    {
        #region ** fields

        private CancellationTokenSource _cancellationToken;
        private OneDriveHelper _helper = new OneDriveHelper();
        private string _accessToken;

        #endregion

        #region ** initialization

        public DemoPdf()
        {
            InitializeComponent();
        }

        #endregion

        #region ** implementation

        public async void HandleButtonClick(object sender, RoutedEventArgs e)
        {
            // get sender button
            var btn = sender as Button;
            await UploadPDFToOneDrive((string)btn.Content);
        }

        private void CancelClick(object sender, RoutedEventArgs e)
        {
            if (_cancellationToken != null)
                _cancellationToken.Cancel();
        }

        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();

                    // create document
                    var pdf = new C1PdfDocument(PaperKind.Letter);
                    pdf.Clear();

                    // set document info
                    var di = pdf.DocumentInfo;
                    di.Author = "ComponentOne";
                    di.Subject = "C1.Silverlight.Pdf demo.";
                    di.Title = fileName;
                    // create document
                    switch (di.Title)
                    {
                        case "Images":
                            await PdfCodeSamples.CreateDocumentImages(pdf);
                            break;
                        case "Paper Sizes":
                            PdfCodeSamples.CreateDocumentPaperSizes(pdf);
                            break;
                        case "Table of Contents":
                            PdfCodeSamples.CreateDocumentTOC(pdf);
                            break;
                        case "Text":
                            PdfCodeSamples.CreateDocumentText(pdf);
                            break;
                        case "Graphics":
                            PdfCodeSamples.CreateDocumentGraphics(pdf);
                            break;
                    }

                    // render footers
                    // this reopens each page and adds content to them (now we know the page count).
                    var font = new Font("Arial", 8, PdfFontStyle.Bold);
                    var fmt = new StringFormat();
                    fmt.Alignment = HorizontalAlignment.Right;
                    fmt.LineAlignment = VerticalAlignment.Bottom;
                    for (int page = 0; page < pdf.Pages.Count; page++)
                    {
                        pdf.CurrentPage = page;
                        var text = string.Format("C1.Silverlight.Pdf: {0}, page {1} of {2}",
                            di.Title,
                            page + 1,
                            pdf.Pages.Count);
                        pdf.DrawString(
                            text,
                            font,
                            Colors.DarkGray,
                            PdfUtils.Inflate(pdf.PageRectangle, -72, -36),
                            fmt);
                    }

                    // save document
                    prog.Text = "Uploading file to OneDrive...";
                    var stream = new MemoryStream();
                    pdf.Save(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;
            }
        }

        #endregion
    }
}
