﻿Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports XMLSpyLib

Namespace AuthenticIDEPlugin
    Public Class PlugInClass
        Implements XMLSpyPlugInLib.IXMLSpyPlugIn

#Region "helpers"

        Protected Function GetPlugInPath() As String
            Dim sDLLPath As String = System.Reflection.Assembly.GetExecutingAssembly().Location
            Return System.IO.Path.GetDirectoryName(sDLLPath)
        End Function

        Public Class WindowWrapper
            Implements System.Windows.Forms.IWin32Window
            Public Sub New(ByVal handle As IntPtr)
                _hwnd = handle
            End Sub

            Public ReadOnly Property Handle() As IntPtr Implements System.Windows.Forms.IWin32Window.Handle
                Get
                    Return _hwnd
                End Get
            End Property

            Private _hwnd As IntPtr
        End Class

#End Region

#Region "IXMLSpyPlugIn Members"

        Public Function GetDescription() As String Implements XMLSpyPlugInLib.IXMLSpyPlugIn.GetDescription
            Return "Authentic VB.NET Sample PlugIn; This plugin demonstrates a simple implementation of an IDE plug-in for Authentic Desktop in VB.NET. It allows to locate the active document in the current Project if present."
        End Function

        Public Function GetUIModifications() As String Implements XMLSpyPlugInLib.IXMLSpyPlugIn.GetUIModifications
            Dim sPath As String = GetPlugInPath()

            ' possible IOException not catched
            Dim myFile As New System.IO.StreamReader(sPath & "\config.xml")
            Dim sRet As String = myFile.ReadToEnd()
            myFile.Close()

            ' this replaces the token "**path**" from the XML file with
            ' the actual installation path of the plug-in to get the image file
            Return sRet.Replace("**path**", sPath)
        End Function

        Public Sub OnCommand(ByVal nID As Integer, ByVal AuthenticApp As Object) Implements XMLSpyPlugInLib.IXMLSpyPlugIn.OnCommand
            Dim iApp As IApplication2 = DirectCast(AuthenticApp, IApplication2)
            If iApp Is Nothing Then
                Return
            End If

            Dim iDoc As IDocument = iApp.ActiveDocument
            If iDoc Is Nothing Then
                Return
            End If

            Dim bFound As Boolean = False
            Dim bDone As Boolean = False

            ' "Find in project" command
            If nID = 3 OrElse nID = 6 Then
                SelectPathInProject(iApp.CurrentProject.RootItems, iApp.ActiveDocument.FullName, True, bFound)
                bDone = True
            End If

            ' check for "fill green"
            If nID = 4 OrElse nID = 7 Then
                iApp.CurrentProject.ClearSelection()

                SelectPathInProject(iApp.CurrentProject.RootItems, iApp.ActiveDocument.FullName, False, bFound)
                bDone = True
            End If

            If nID = 8 Then
                m_bAutoSelectDoc = Not m_bAutoSelectDoc
            End If

            If bDone AndAlso Not bFound Then
                System.Windows.Forms.MessageBox.Show(New WindowWrapper(CType(iApp.WindowHandle, IntPtr)), "The active document is not part of the open project!", "Authentic IDE VB.NET Sample PlugIn")
            End If

            ' release unused objects
            GC.Collect()
        End Sub


        Public Function OnEvent(ByVal nEventID As Integer, ByRef arrayParameters As Object(), ByVal AuthenticApp As Object) As Object Implements XMLSpyPlugInLib.IXMLSpyPlugIn.OnEvent
            Throw New NotImplementedException()
        End Function


        Public Function OnUpdateCommand(ByVal nID As Integer, ByVal AuthenticApp As Object) As XMLSpyPlugInLib.SPYUpdateAction Implements XMLSpyPlugInLib.IXMLSpyPlugIn.OnUpdateCommand
            Dim action As XMLSpyPlugInLib.SPYUpdateAction = XMLSpyPlugInLib.SPYUpdateAction.spyDisable

            Dim iApp As IApplication = DirectCast(AuthenticApp, IApplication)
            If iApp Is Nothing Then
                Return action
            End If

            Dim iDoc As IDocument = iApp.ActiveDocument
            If iDoc Is Nothing Then
                Return action
            End If

            If iApp.CurrentProject Is Nothing Then
                Return action
            End If

            If nID = 8 Then
                If m_bAutoSelectDoc Then
                    action = XMLSpyPlugInLib.SPYUpdateAction.spyEnable Or XMLSpyPlugInLib.SPYUpdateAction.spyCheck
                Else
                    action = XMLSpyPlugInLib.SPYUpdateAction.spyEnable Or XMLSpyPlugInLib.SPYUpdateAction.spyUncheck
                End If
            Else
                action = XMLSpyPlugInLib.SPYUpdateAction.spyEnable
            End If

            Dim strActiveDoc As String = GetActiveDocFullPath(iApp)
            Dim strLastCurrentDoc As String = m_strCurrentDoc

            Dim bNewActiveDoc As Boolean = False
            Dim bLastActiveDocEmpty As Boolean = (m_strCurrentDoc Is Nothing) OrElse (m_strCurrentDoc.Length = 0)

            If Not bLastActiveDocEmpty Then
                If Not m_strCurrentDoc.Equals(strActiveDoc, StringComparison.OrdinalIgnoreCase) Then
                    bNewActiveDoc = True

                    m_strCurrentDoc = strActiveDoc
                End If
            Else
                bNewActiveDoc = strActiveDoc.Length > 0

                If bNewActiveDoc Then
                    m_strCurrentDoc = strActiveDoc
                End If
            End If

            If m_bAutoSelectDoc AndAlso bNewActiveDoc Then
                Dim bFound As Boolean = False
                SelectPathInProject(iApp.CurrentProject.RootItems, iApp.ActiveDocument.FullName, True, bFound)
            End If

            ' release unused objects
            GC.Collect()

            Return action
        End Function

#End Region

        Private Function CountItems(ByVal iParent As IXMLData) As Long
            Dim nRes As Long = 0
            For nChild As Integer = 0 To iParent.CountChildren() - 1
                nRes += 1
                nRes += CountItems(iParent.GetChild(nChild))
            Next
            Return nRes
        End Function


        Private Sub SelectPathInProject(ByVal ipProjectItems As ISpyProjectItems, ByVal strPath As String, ByVal bStopOnFirst As Boolean, ByRef bFound As Boolean)
            For nIdx As Integer = 1 To ipProjectItems.Count
                Dim ipItem As ISpyProjectItem2 = ipProjectItems(nIdx)

                If ipItem IsNot Nothing Then
                    Dim strName As String = ipItem.Name
                    Dim eItemType As SPYProjectItemTypes = ipItem.ItemType

                    If eItemType = SPYProjectItemTypes.spyFolderItem Then
                        '2
                        SelectPathInProject(ipItem.ChildItems, strPath, bStopOnFirst, bFound)

                        If bFound AndAlso bStopOnFirst Then
                            Return
                        End If
                    ElseIf eItemType = SPYProjectItemTypes.spyUnknownItem Then
                        '0
                    ElseIf eItemType = SPYProjectItemTypes.spyFileItem Then
                        '1
                        If strPath = ipItem.Path Then
                            ipItem.[Select](True, bStopOnFirst)
                            bFound = True

                            If bStopOnFirst Then
                                Return
                            End If
                        End If
                    End If
                End If
            Next
        End Sub


        Private Function GetActiveDocFullPath(ByVal iApp As IApplication) As String
            If iApp IsNot Nothing Then
                Dim iDoc As IDocument3 = iApp.ActiveDocument

                If iDoc IsNot Nothing Then
                    Return iDoc.FullName
                End If
            End If

            Return ""
        End Function

        Private m_strCurrentDoc As String
        Private m_bAutoSelectDoc As Boolean


    End Class
End Namespace

