Option Explicit On
Option Strict On
Imports System.ComponentModel
Imports System.IO
Imports Microsoft.Win32
Public Class Form1
    Private ToolStrip As New ToolStrip With {.ImageScalingSize = New Size(48, 48)}
    Private WithEvents DownloadButton As New ToolStripButton With {.AutoSize = True,
                                                                   .ImageAlign = ContentAlignment.BottomCenter,
                                                                   .ImageScaling = ToolStripItemImageScaling.SizeToFit,
                                                                   .Text = "ダウンロード",
                                                                   .TextAlign = ContentAlignment.BottomCenter,
                                                                   .DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,
                                                                   .Size = New Size(100, 80),
                                                                   .TextImageRelation = TextImageRelation.ImageAboveText}
    Private WithEvents Favicon As New PictureBox
    Private StatusStrip As New StatusStrip
    Private Progress As New ToolStripProgressBar
    Private Status As New ToolStripLabel
    Private Panel As New Panel With {.Dock = DockStyle.Fill}
    Private WebBrowser As New WebBrowser With {.Dock = DockStyle.Fill,
                                               .ScriptErrorsSuppressed = True}
    Private baseUrl As New Uri("https://print-kids.net/")
    Private faviconUrl As New Uri(Me.baseUrl, "/img/favicon.ico")
    Private downloadList As New List(Of link)
    Private abort As Boolean = False
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        BrowserEmulation.CreateRenderingModeRegkey(BrowserEmulation.Emulation.IE11Edge)
        Me.Text = "ぷりんときっずダウンローダー"
        Me.KeyPreview = True
        Me.Size = New Size(1024, 678)
        Me.Favicon.LoadAsync(faviconUrl.ToString)
        Me.ToolStrip.Items.Add(Me.DownloadButton)
        Me.StatusStrip.Items.AddRange({Me.Progress, Me.Status})
        Me.Panel.Controls.Add(Me.WebBrowser)
        Me.Controls.AddRange({Me.StatusStrip, Me.Panel, Me.ToolStrip})
        Me.WebBrowser.Navigate(Me.baseUrl)
    End Sub
    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        BrowserEmulation.DeleteRenderingModeRegkey()
    End Sub
    Private Sub Favicon_LoadCompleted(sender As Object, e As AsyncCompletedEventArgs) Handles Favicon.LoadCompleted
        Me.DownloadButton.Image = Me.Favicon.Image
        Me.Icon = Icon.FromHandle(DirectCast(Me.Favicon.Image, Bitmap).GetHicon)
        Dialog1.Icon = Me.Icon
    End Sub
    Private Sub Download_Click(sender As Object, e As EventArgs) Handles DownloadButton.Click
        Me.Panel.Enabled = False
        Me.DownloadButton.Enabled = False
        Me.abort = False
        AddHandler Me.WebBrowser.DocumentCompleted, AddressOf WebBrowser_DocumentCompleted
        Me.WebBrowser.Navigate(Me.WebBrowser.Url)
    End Sub
    Private Sub WebBrowser_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs)
        Static downloadList As New List(Of link)
        Dim browser As WebBrowser = DirectCast(sender, WebBrowser)
        If e.Url.Equals(browser.Url) Then
            Dim document As HtmlDocument = browser.Document
            Dim panNav As String = document.GetElementById("pan-nav")?.GetElementsByTagName("span") _
                                           .Cast(Of HtmlElement) _
                                           .Select(Function(spanTag) spanTag.InnerText) _
                                           .Aggregate(String.Empty, Function(retValue As String, title As String) Path.Combine(retValue, title))
            Select Case True
                Case document.GetElementById("topic").GetElementsByTagName("section").Count > 0
                    
                    downloadPdfs(document, downloadList, panNav)
                Case document.GetElementById("menu").GetElementsByTagName("aside")(1).GetAttribute("className") = "text-anime"
                    
                    Dim categoryLinks = document.GetElementById("menu").GetElementsByTagName("aside")(1).GetElementsByTagName("a") _
                                                .Cast(Of HtmlElement) _
                                                .Select(Function(anchorElement) New link(New Uri(anchorElement.GetAttribute("href")), anchorElement.InnerText))
                    downloadCategories(document, downloadList, categoryLinks, panNav)
                Case Else
                    
                    Dim categoryLinks = document.GetElementById("picture").GetElementsByTagName("a") _
                                                .Cast(Of HtmlElement) _
                                                .Select(Function(anchorElement) New link(New Uri(anchorElement.GetAttribute("href")), anchorElement.InnerText))
                    downloadCategories(document, downloadList, categoryLinks, panNav)
            End Select
            
            If downloadList.Count > 0 Then
                Dim lastItem As link = downloadList.Last
                downloadList.Remove(lastItem)
                Me.WebBrowser.Navigate(lastItem.Uri)
            Else
                RemoveHandler Me.WebBrowser.DocumentCompleted, AddressOf WebBrowser_DocumentCompleted
                Me.Panel.Enabled = True
                Me.DownloadButton.Enabled = True
                Me.WebBrowser.Document.Focus()
            End If
        End If
    End Sub
    
    Private Sub downloadCategories(document As HtmlDocument, downloadList As List(Of link), categorylinks As IEnumerable(Of link), panNav As String)
        If downloadList.Count > 0 Then
            downloadList.AddRange(categorylinks.Reverse)
        Else
            Dialog1.CheckedListBox.Items.AddRange(categorylinks.ToArray)
            For i As Integer = 0 To Dialog1.CheckedListBox.Items.Count - 1
                Dialog1.CheckedListBox.SetItemChecked(i, True)
            Next
            Dim Category As String = Path.GetFileName(panNav)
            Dialog1.Text = If(Category = "", "大カテゴリを選択してダウンロード", Category & "カテゴリから選択してダウンロード")
            Dialog1.ShowDialog()
            If Dialog1.DialogResult = DialogResult.OK Then
                downloadList.AddRange(Dialog1.CheckedListBox.CheckedItems.Cast(Of link).Reverse)
            End If
            Dialog1.CheckedListBox.Items.Clear()
        End If
    End Sub
    Private Sub downloadPdfs(document As HtmlDocument, downloadList As List(Of link), panNav As String)
        
        document.GetElementsByTagName("section")(0).ScrollIntoView(True)
        
        Dim pdfLinks = document.GetElementById("topic").GetElementsByTagName("a") _
                               .Cast(Of HtmlElement) _
                               .Select(Function(anchorElement) New With {.Uri = New Uri(anchorElement.GetAttribute("href")), .HtmlElement = anchorElement}) _
                               .Where(Function(anchorElement) baseUrl.IsBaseOf(anchorElement.Uri) AndAlso Path.GetExtension(anchorElement.Uri.AbsoluteUri).ToLower = ".pdf") _
                               .Select(Function(anchorElement) New link(anchorElement.Uri, anchorElement.HtmlElement.GetElementsByTagName("p")(0).InnerText))
        
        Dim downloadDir = panNav.Replace("ホーム\無料プリント", "ぷりんときっず")
        
        downloadDir = Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, downloadDir)
        If Not Directory.Exists(downloadDir) Then
            My.Computer.FileSystem.CreateDirectory(Path.Combine(downloadDir))
        End If
        
        Dim Progress As Integer = 0
        Me.Progress.Maximum = pdfLinks.Count
        SetProgress(Progress, "")
        For Each pdfLink As link In pdfLinks
            Dim DownloadFileName As String = Path.Combine(downloadDir, pdfLink.Text.Replace(" ", "") & ".pdf")
            Dim DownloadUrl As String = Path.GetFileName(pdfLink.Uri.AbsoluteUri)
            Dim Status As String = " スキップ(ESCキーで停止)"
            If Not File.Exists(DownloadFileName) Then
                My.Computer.Network.DownloadFile(pdfLink.Uri, DownloadFileName)
                Status = " ダウンロード中...(ESCキーで停止)"
            End If
            SetProgress(Progress, Progress + 1 & "/" & Me.Progress.Maximum & " " & Path.GetFileName(downloadDir) & " " & DownloadUrl & " " & Status)
            Progress += 1
            
            If abort Then
                SetProgress(Progress, "ダウンロード停止")
                downloadList.Clear()
                Exit Sub
            End If
        Next
        SetProgress(Me.Progress.Maximum, Path.GetFileName(downloadDir) & " ダウンロード完了")
    End Sub
    
    
    Private Sub SetProgress(Value As Integer, Message As String)
        Me.Progress.Maximum += 1
        Me.Progress.Value = Value + 1
        Me.Progress.Value -= 1
        Me.Progress.Maximum -= 1
        Me.Status.Text = Message
        Me.StatusStrip.Refresh()
    End Sub
    Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
        Me.abort = (e.KeyData = Keys.Escape)
    End Sub
    Private Class link
        Property Uri As Uri
        Property Text As String
        Public Sub New(Uri As Uri, Text As String)
            Me.Uri = Uri
            Me.Text = Text
        End Sub
        Public Overrides Function ToString() As String
            Return Me._Text
        End Function
    End Class
End Class
Public Class BrowserEmulation
    Public Enum Emulation
        IE11Edge = 11001
        IE11 = 11000
        IE10Std = 10001
        IE10 = 10000
        IE9Std = 9999
        IE9 = 9000
        IE8Std = 8888
        IE8 = 8000
        IE7 = 7000
    End Enum
    Private Const FEATURE_BROWSER_EMULATION As String = "Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"
    Public Shared Sub CreateRenderingModeRegkey(EmulationMode As Emulation)
        Using Regkey As RegistryKey = Registry.CurrentUser.CreateSubKey(FEATURE_BROWSER_EMULATION)
            Regkey.SetValue(GetReleaseBuildName, EmulationMode, RegistryValueKind.DWord)
            Regkey.SetValue(GetDebugBuildName, EmulationMode, RegistryValueKind.DWord)
        End Using
    End Sub
    Public Shared Sub DeleteRenderingModeRegkey()
        Using Regkey As RegistryKey = Registry.CurrentUser.CreateSubKey(FEATURE_BROWSER_EMULATION)
            Regkey.DeleteValue(GetReleaseBuildName)
            Regkey.DeleteValue(GetDebugBuildName)
        End Using
    End Sub
    Private Shared Function GetReleaseBuildName() As String
        Return Path.GetFileName(Application.ExecutablePath)
    End Function
    Private Shared Function GetDebugBuildName() As String
        Return GetReleaseBuildName.Replace(".exe", ".svhost.exe")
    End Function
End Class