Imports System.IO
Imports System.Threading.Tasks
Imports Windows.Data.Pdf
Imports Windows.Storage
Imports Windows.Storage.Streams

Partial Public Class PdfViewer
   Inherits UserControl

   Public Property PdfPath As String
      Get
         Return CStr(GetValue(PdfPathProperty))
      End Get
      Set(value As String)
         SetValue(PdfPathProperty, value)
      End Set
   End Property

   Public Shared ReadOnly PdfPathProperty As DependencyProperty = DependencyProperty.Register("PdfPath",
                                                                                              GetType(String),
                                                                                              GetType(PdfViewer),
                                                                                              New PropertyMetadata(Nothing, propertyChangedCallback:=AddressOf OnPdfPathChanged))

   Private Shared Sub OnPdfPathChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
      Dim pdfDrawer As PdfViewer = CType(d, PdfViewer)

      If Not String.IsNullOrEmpty(pdfDrawer.PdfPath) Then
         Dim path = System.IO.Path.GetFullPath(pdfDrawer.PdfPath)
         StorageFile.GetFileFromPathAsync(path).AsTask().ContinueWith(Function(t) PdfDocument.LoadFromFileAsync(t.Result).AsTask()).Unwrap().ContinueWith(Function(t2) PdfToImages(pdfDrawer, t2.Result), TaskScheduler.FromCurrentSynchronizationContext())
      End If
   End Sub

   Sub New()
      InitializeComponent()
   End Sub

   ''' <summary>
   ''' Funzione che trasforma le pagine del pdf in immagine
   ''' </summary>
   ''' <param name="pdfViewer">PDF da trasformare</param>
   ''' <param name="pdfDoc">Singola pagina del PDf</param>
   ''' <returns></returns>
   Private Shared Async Function PdfToImages(pdfViewer As PdfViewer, pdfDoc As PdfDocument) As Task
      Dim items As ItemCollection = pdfViewer.PagesContainer.Items
      items.Clear()

      If IsNothing(pdfDoc) Then Return

      For i As Integer = 0 To pdfDoc.PageCount - 1
         Using page As PdfPage = pdfDoc.GetPage(i)
            Dim bitmap As BitmapImage = Await PageToBitmapAsync(page)
            Dim image As New Image With {
                .Source = bitmap,
                .Width = bitmap.PixelWidth,
                .Height = bitmap.PixelHeight,
                .HorizontalAlignment = HorizontalAlignment.Center,
                .Margin = New Thickness(5, 20, 5, 20),
                .SnapsToDevicePixels = True,
                .Stretch = Stretch.UniformToFill
            }
            items.Add(image)
         End Using
      Next
   End Function

   ''' <summary>
   ''' Funzione che trasforma la singola pagina del PDF in bitmap
   ''' </summary>
   ''' <param name="page">Singola pagina del PDF che verrà trasformata in bitmap</param>
   ''' <returns></returns>
   Private Shared Async Function PageToBitmapAsync(page As PdfPage) As Task(Of BitmapImage)
      Dim image As New BitmapImage()

      Using stream = New InMemoryRandomAccessStream()
         Await page.RenderToStreamAsync(stream)
         image.BeginInit()
         image.CreateOptions = BitmapCreateOptions.PreservePixelFormat
         image.DecodePixelWidth = page.Size.Width
         image.DecodePixelHeight = page.Size.Height
         image.CacheOption = BitmapCacheOption.OnLoad
         image.StreamSource = stream.AsStream()
         image.UriSource = Nothing
         image.EndInit()
      End Using
      'image.Freeze()

      Return image
   End Function
End Class
