Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Text
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Linq
Imports System.Collections.Specialized
Imports BacklinksWarrior.Extensions

Public Class ResultView
    Implements INotifyPropertyChanged

    Private _results As ObservableCollection(Of LinkSite)
    Private _lastDirection As ListSortDirection = ListSortDirection.Descending
    Private _lastHeaderClicked As GridViewColumnHeader
    Private ReadOnly _pageRankColumn As GridViewColumn

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        _results = New ObservableCollection(Of LinkSite)()
        _pageRankColumn = GridViewColumnBuilder.CreatePageRankColumn()

        ' Disable Google PR functionality
        'AddHandler _results.CollectionChanged, AddressOf _results_CollectionChanged
        'AddHandler Me.PropertyChanged, Sub(s, e)
        '                                   If e.PropertyName = "Results" Then
        '                                       DisplayPRColumnIfNeeded()
        '                                   End If
        '                               End Sub
    End Sub

    Public Sub SelectAll()
        lstKeywords.SelectAll()
    End Sub

    Public Sub lstKeywords_Click(sender As Object, e As RoutedEventArgs)
        Dim button = TryCast(e.OriginalSource, Button)

        ' If the note button (or any button in the listview) is clicked.
        If Not button Is Nothing Then
            lstKeywords.SelectedItem = button.DataContext
            Me.VeiwEditNotes()
            Exit Sub
        End If

        If TryCast(e.OriginalSource, GridViewColumnHeader) Is Nothing Then Exit Sub

        ' If the header is clicked
        Dim headerClicked As GridViewColumnHeader = CType(e.OriginalSource, GridViewColumnHeader)
        Dim direction As ListSortDirection

        If Not headerClicked Is Nothing Then
            If headerClicked.Role <> GridViewColumnHeaderRole.Padding Then
                If Not headerClicked Is _lastHeaderClicked Then
                    direction = ListSortDirection.Ascending
                Else
                    If _lastDirection = ListSortDirection.Ascending Then
                        direction = ListSortDirection.Descending
                    Else
                        direction = ListSortDirection.Ascending
                    End If
                End If
            End If

            Dim header As String = headerClicked.Column.Header
            Sort(header, direction)

            If direction = ListSortDirection.Ascending Then
                headerClicked.Column.HeaderTemplate = Resources("HeaderTemplateArrowUp")
            Else
                headerClicked.Column.HeaderTemplate = Resources("HeaderTemplateArrowDown")
            End If

            If Not _lastHeaderClicked Is Nothing AndAlso Not _lastHeaderClicked Is headerClicked Then
                _lastHeaderClicked.Column.HeaderTemplate = Nothing
            End If

            _lastHeaderClicked = headerClicked
            _lastDirection = direction
        End If

    End Sub

    'Private Sub _results_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
    '    DisplayPRColumnIfNeeded()
    'End Sub

    'Private Sub DisplayPRColumnIfNeeded()
    '    ' HACK: There needs to be a better way of hiding column...
    '    ' This uses a singleton style class PageRankColumnBuilder that returns a column that can be added to (or removed from) the grid view
    '    ' If _results.Where(Function(r) r.PageRank > 0).Count() > 0 Then ' If any of the results have PageRanks then display the PR column
    '    ' 
    '    '  DISABLE PR 3 Oct 2016 - Disable Google Page Rank functionality
    '    '
    '    'If My.Settings.PREnabled Then ' The old version seems to use this logic.
    '    '    Dim addColumn As [Delegate] = Sub()
    '    '                                      Dim gv = CType(lstKeywords.View, GridView)
    '    '                                      If Not gv.Columns.Contains(_pageRankColumn) Then
    '    '                                          gv.Columns.Insert(2, _pageRankColumn)
    '    '                                      End If
    '    '                                  End Sub

    '    '    Dispatcher.Invoke(addColumn)
    '    'Else
    '    Dim removeColumn As [Delegate] = Sub()
    '                                             Dim gv = CType(lstKeywords.View, GridView)
    '                                             If gv.Columns.Contains(_pageRankColumn) Then
    '                                                 gv.Columns.Remove(_pageRankColumn)
    '                                             End If
    '                                         End Sub

    '        Dispatcher.Invoke(removeColumn)
    '    'End If
    'End Sub


    Public Sub Sort(header As String, direction As ListSortDirection)
        Dim headerToKey = Function(k As LinkSite)
                              Select Case header
                                  Case "Status"
                                      Return k.Status
                                  Case "Keyword"
                                      Return k.Keyword
                                  Case "PR"
                                      Return k.PageRank
                                  Case "Page URL"
                                      Return k.PageUrl
                                  Case "Notes"
                                      Return k.Notes
                                  Case Else
                                      Return Nothing
                              End Select
                          End Function

        If direction = ListSortDirection.Ascending Then
            Results = _results.OrderBy(headerToKey).ToList()
        Else
            Results = _results.OrderByDescending(headerToKey).ToList()
        End If
    End Sub

    Public Sub VeiwEditNotes()
        RaiseEvent MadeDirty()
        Dim dlg As New NotesDialog()
        Dim keyword = CType(lstKeywords.SelectedItem, LinkSite)
        If Not keyword Is Nothing Then
            dlg.Notes = keyword.Notes
            If dlg.ShowDialog() = DialogResult.OK Then
                keyword.Notes = dlg.Notes
                NotifyPropertyChanged("Results")
            End If
        End If
    End Sub

    Public Sub CopyToClipboard()
        Dim item = TryCast(lstKeywords.SelectedItem, LinkSite)

        If item Is Nothing Then
            MessageBox.Show("No items were select for copy.", "Invalid Selection", MessageBoxButton.OK, MessageBoxImage.Exclamation)
            Exit Sub
        End If

        Clipboard.SetText(item.PageUrl)
    End Sub

    Public Sub RemoveSelected()
        RemoveItems(lstKeywords.SelectedItems)
    End Sub

    Public Sub SetStatusNew()
        For Each k As LinkSite In lstKeywords.SelectedItems
            k.Status = LinkSiteStatus.New
        Next

        RaiseEvent MadeDirty()
        NotifyPropertyChanged("Results")
    End Sub

    Public Sub SetStatusAdded()
        For Each k As LinkSite In lstKeywords.SelectedItems
            k.Status = LinkSiteStatus.Added
        Next

        RaiseEvent MadeDirty()
        NotifyPropertyChanged("Results")
    End Sub

    Public Sub SetStatusIgnored()
        For Each k As LinkSite In lstKeywords.SelectedItems
            k.Status = LinkSiteStatus.Ignored
        Next

        RaiseEvent MadeDirty()
        NotifyPropertyChanged("Results")
    End Sub

    Public Sub OpenSelectedUrl()
        If lstKeywords.SelectedItem IsNot Nothing Then
            Process.Start(CType(lstKeywords.SelectedItem, LinkSite).PageUrl)
        End If
    End Sub

    Private Sub RemoveItems(items As IList)
        Dim aselected(items.Count - 1) As LinkSite
        items.CopyTo(aselected, 0)

        Dim selectedResults As New List(Of LinkSite)(aselected)
        For Each result In selectedResults
            Me.Results.Remove(result)
        Next

        RaiseEvent PropertyChanged(Nothing, New PropertyChangedEventArgs("Results"))

    End Sub

    Public Sub AddResults(results As IList(Of LinkSite))
        If _results Is Nothing Then
            _results = New ObservableCollection(Of LinkSite)()
        End If

        For Each result In results
            _results.Add(result)
        Next
        NotifyPropertyChanged("Results")
    End Sub

    Public Property Results As IList(Of LinkSite)
        Get
            Return _results
        End Get
        Set(value As IList(Of LinkSite))
            _results = New ObservableCollection(Of LinkSite)(value)
            NotifyPropertyChanged("Results")
        End Set
    End Property

    Public ReadOnly Property SelectedResults As IList
        Get
            Return lstKeywords.SelectedItems
        End Get
    End Property

    Public Event MadeDirty()

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Private Sub NotifyPropertyChanged(propertyName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub

    Private Sub lstKeywords_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles lstKeywords.SelectionChanged
        NotifyPropertyChanged("SelectedKeywords")
    End Sub

    Private Sub CopyUrl_Executed(sender As System.Object, e As System.Windows.Input.ExecutedRoutedEventArgs)
        CopyToClipboard()
    End Sub

    Private Sub ViewNotes_Executed(sender As System.Object, e As System.Windows.Input.ExecutedRoutedEventArgs)
        VeiwEditNotes()
    End Sub

    Private Sub RemoveSelected_Executed(sender As System.Object, e As System.Windows.Input.ExecutedRoutedEventArgs)
        RemoveSelected()
    End Sub

    Private Sub OpenUrl_Executed(sender As System.Object, e As System.Windows.Input.ExecutedRoutedEventArgs)
        If TypeOf e.Parameter Is String Then
            Process.Start(e.Parameter)
        End If
    End Sub

    Private Sub StatusNew_Executed(sender As Object, e As System.Windows.Input.ExecutedRoutedEventArgs)
        SetStatusNew()
    End Sub

    Private Sub StatusAdded_Executed(sender As Object, e As System.Windows.Input.ExecutedRoutedEventArgs)
        SetStatusAdded()
    End Sub

    Private Sub StatusIgnored_Executed(sender As Object, e As System.Windows.Input.ExecutedRoutedEventArgs)
        SetStatusIgnored()
    End Sub
End Class

Public Class Commands
    Public Shared ReadOnly StatusNew As New RoutedUICommand("New", "StatusNew", GetType(ResultView))
    Public Shared ReadOnly StatusAdded As New RoutedUICommand("Link Added", "StatusAdded", GetType(ResultView))
    Public Shared ReadOnly StatusIgnored As New RoutedUICommand("Ignored", "StatusIgnored", GetType(ResultView))
    Public Shared ReadOnly OpenUrl As New RoutedUICommand("Open URL", "OpenUrl", GetType(ResultView))
    Public Shared ReadOnly CopyUrl As New RoutedUICommand("Copy URL to Clipboard", "CopyUrl", GetType(ResultView))
    Public Shared ReadOnly ViewNotes As New RoutedUICommand("View/Edit User Notes", "ViewNotes", GetType(ResultView))
    Public Shared ReadOnly RemoveSelected As New RoutedUICommand("Remove Selected", "RemoveSelected", GetType(ResultView))
End Class
