Option Strict On

Imports System.ComponentModel
Imports System.IO
Imports System.Xml.Serialization


Imports Mbark.BusinessObjects.EntityClasses
Imports Mbark.UI
Imports Mbark.SystemCoordinationMessages

Namespace Mbark.SystemCoordination

    Public Class ManagerForm
        Inherits StatefulForm

#Region " Windows Form Designer generated code "

        Public Sub New()
            MyBase.New()

            'This call is required by the Windows Form Designer.
            InitializeComponent()

            'Add any initialization after the InitializeComponent() call

        End Sub

        'Form overrides dispose to clean up the component list.
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If Not (components Is Nothing) Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub

        'Required by the Windows Form Designer
        Private components As System.ComponentModel.IContainer

        'NOTE: The following procedure is required by the Windows Form Designer
        'It can be modified using the Windows Form Designer.  
        'Do not modify it using the code editor.
        Friend WithEvents BackgroundPanel As Syncfusion.Windows.Forms.Tools.GradientPanel
        Friend WithEvents MessageGrid As Syncfusion.Windows.Forms.Grid.GridControl
        Friend WithEvents LeftPanel As Syncfusion.Windows.Forms.Tools.GradientPanel
        Friend WithEvents NameLabel As Syncfusion.Windows.Forms.Tools.GradientLabel
        Friend WithEvents MinimizeButton As Syncfusion.Windows.Forms.ButtonAdv
        Friend WithEvents CloseButton As Syncfusion.Windows.Forms.ButtonAdv
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.BackgroundPanel = New Syncfusion.Windows.Forms.Tools.GradientPanel
            Me.MinimizeButton = New Syncfusion.Windows.Forms.ButtonAdv
            Me.MessageGrid = New Syncfusion.Windows.Forms.Grid.GridControl
            Me.NameLabel = New Syncfusion.Windows.Forms.Tools.GradientLabel
            Me.LeftPanel = New Syncfusion.Windows.Forms.Tools.GradientPanel
            Me.CloseButton = New Syncfusion.Windows.Forms.ButtonAdv
            CType(Me.BackgroundPanel, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.BackgroundPanel.SuspendLayout()
            CType(Me.MessageGrid, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me.LeftPanel, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.LeftPanel.SuspendLayout()
            Me.SuspendLayout()
            '
            'BackgroundPanel
            '
            Me.BackgroundPanel.BackColor = System.Drawing.SystemColors.ControlLightLight
            Me.BackgroundPanel.Border3DStyle = System.Windows.Forms.Border3DStyle.RaisedOuter
            Me.BackgroundPanel.BorderColor = System.Drawing.Color.Black
            Me.BackgroundPanel.Controls.Add(Me.MinimizeButton)
            Me.BackgroundPanel.Controls.Add(Me.MessageGrid)
            Me.BackgroundPanel.Controls.Add(Me.NameLabel)
            Me.BackgroundPanel.Controls.Add(Me.LeftPanel)
            Me.BackgroundPanel.Dock = System.Windows.Forms.DockStyle.Fill
            Me.BackgroundPanel.Location = New System.Drawing.Point(0, 0)
            Me.BackgroundPanel.Name = "BackgroundPanel"
            Me.BackgroundPanel.Size = New System.Drawing.Size(440, 230)
            Me.BackgroundPanel.TabIndex = 1
            '
            'MinimizeButton
            '
            Me.MinimizeButton.Appearance = Syncfusion.Windows.Forms.ButtonAppearance.OfficeXP
            Me.MinimizeButton.BackColor = System.Drawing.Color.Transparent
            Me.MinimizeButton.ButtonType = Syncfusion.Windows.Forms.Tools.ButtonTypes.Down
            Me.MinimizeButton.ComboEditBackColor = System.Drawing.Color.Empty
            Me.MinimizeButton.Font = New System.Drawing.Font("Verdana", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
            Me.MinimizeButton.IsMouseDown = False
            Me.MinimizeButton.Location = New System.Drawing.Point(416, 2)
            Me.MinimizeButton.Name = "MinimizeButton"
            Me.MinimizeButton.Size = New System.Drawing.Size(16, 16)
            Me.MinimizeButton.TabIndex = 5
            Me.MinimizeButton.TabStop = False
            Me.MinimizeButton.UseVisualStyle = True
            '
            'MessageGrid
            '
            Me.MessageGrid.AllowScrollCurrentCellInView = Syncfusion.Windows.Forms.Grid.GridScrollCurrentCellReason.None
            Me.MessageGrid.AllowSelection = Syncfusion.Windows.Forms.Grid.GridSelectionFlags.None
            Me.MessageGrid.BackColor = System.Drawing.SystemColors.ControlLightLight
            Me.MessageGrid.ColCount = 1
            Me.MessageGrid.ControllerOptions = Syncfusion.Windows.Forms.Grid.GridControllerOptions.None
            Me.MessageGrid.DefaultColWidth = 300
            Me.MessageGrid.DefaultGridBorderStyle = Syncfusion.Windows.Forms.Grid.GridBorderStyle.Solid
            Me.MessageGrid.HScrollBehavior = Syncfusion.Windows.Forms.Grid.GridScrollbarMode.Disabled
            Me.MessageGrid.Location = New System.Drawing.Point(40, 96)
            Me.MessageGrid.Name = "MessageGrid"
            Me.MessageGrid.Properties.BackgroundColor = System.Drawing.SystemColors.ControlLightLight
            Me.MessageGrid.Properties.Buttons3D = False
            Me.MessageGrid.Properties.ColHeaders = False
            Me.MessageGrid.Properties.DisplayHorzLines = False
            Me.MessageGrid.Properties.DisplayVertLines = False
            Me.MessageGrid.Properties.MarkColHeader = False
            Me.MessageGrid.Properties.MarkRowHeader = False
            Me.MessageGrid.Properties.PrintColHeader = False
            Me.MessageGrid.Properties.PrintRowHeader = False
            Me.MessageGrid.Properties.RowHeaders = False
            Me.MessageGrid.ResizeColsBehavior = Syncfusion.Windows.Forms.Grid.GridResizeCellsBehavior.None
            Me.MessageGrid.ResizeRowsBehavior = Syncfusion.Windows.Forms.Grid.GridResizeCellsBehavior.None
            Me.MessageGrid.RowCount = 5
            Me.MessageGrid.Size = New System.Drawing.Size(384, 88)
            Me.MessageGrid.SmartSizeBox = False
            Me.MessageGrid.TabIndex = 4
            '
            'NameLabel
            '
            Me.NameLabel.BackColor = System.Drawing.SystemColors.ControlLightLight
            Me.NameLabel.BackgroundColor = New Syncfusion.Drawing.BrushInfo(Syncfusion.Drawing.GradientStyle.BackwardDiagonal, System.Drawing.Color.LightCyan, System.Drawing.SystemColors.Window)
            Me.NameLabel.BorderSides = CType((((System.Windows.Forms.Border3DSide.Left Or System.Windows.Forms.Border3DSide.Top) _
                        Or System.Windows.Forms.Border3DSide.Right) _
                        Or System.Windows.Forms.Border3DSide.Bottom), System.Windows.Forms.Border3DSide)
            Me.NameLabel.BorderStyle = System.Windows.Forms.Border3DStyle.Adjust
            Me.NameLabel.Dock = System.Windows.Forms.DockStyle.Bottom
            Me.NameLabel.Font = New System.Drawing.Font("Verdana", 12.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
            Me.NameLabel.Location = New System.Drawing.Point(32, 194)
            Me.NameLabel.Name = "NameLabel"
            Me.NameLabel.Size = New System.Drawing.Size(404, 32)
            Me.NameLabel.TabIndex = 3
            Me.NameLabel.Text = "  Manager"
            Me.NameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
            '
            'LeftPanel
            '
            Me.LeftPanel.BackColor = System.Drawing.SystemColors.ControlText
            Me.LeftPanel.Border3DStyle = System.Windows.Forms.Border3DStyle.Flat
            Me.LeftPanel.BorderColor = System.Drawing.Color.Black
            Me.LeftPanel.BorderStyle = System.Windows.Forms.BorderStyle.None
            Me.LeftPanel.Controls.Add(Me.CloseButton)
            Me.LeftPanel.Dock = System.Windows.Forms.DockStyle.Left
            Me.LeftPanel.Location = New System.Drawing.Point(0, 0)
            Me.LeftPanel.Name = "LeftPanel"
            Me.LeftPanel.Size = New System.Drawing.Size(32, 226)
            Me.LeftPanel.TabIndex = 2
            '
            'CloseButton
            '
            Me.CloseButton.Appearance = Syncfusion.Windows.Forms.ButtonAppearance.OfficeXP
            Me.CloseButton.BackColor = System.Drawing.SystemColors.ControlText
            Me.CloseButton.ComboEditBackColor = System.Drawing.Color.Empty
            Me.CloseButton.Font = New System.Drawing.Font("Verdana", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
            Me.CloseButton.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft
            Me.CloseButton.IsMouseDown = False
            Me.CloseButton.Location = New System.Drawing.Point(8, 8)
            Me.CloseButton.Name = "CloseButton"
            Me.CloseButton.Size = New System.Drawing.Size(16, 16)
            Me.CloseButton.TabIndex = 6
            Me.CloseButton.TabStop = False
            Me.CloseButton.UseVisualStyle = False
            '
            'ManagerForm
            '
            Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
            Me.ClientSize = New System.Drawing.Size(440, 230)
            Me.Controls.Add(Me.BackgroundPanel)
            Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
            Me.Name = "ManagerForm"
            Me.Text = "Manager"
            CType(Me.BackgroundPanel, System.ComponentModel.ISupportInitialize).EndInit()
            Me.BackgroundPanel.ResumeLayout(False)
            CType(Me.MessageGrid, System.ComponentModel.ISupportInitialize).EndInit()
            CType(Me.LeftPanel, System.ComponentModel.ISupportInitialize).EndInit()
            Me.LeftPanel.ResumeLayout(False)
            Me.ResumeLayout(False)

        End Sub

#End Region

        Private Shared smSerializer As XmlSerializer
        Protected Overrides Sub OnLoad(ByVal e As EventArgs)
            MyBase.OnLoad(e)


            If smSerializer Is Nothing AndAlso Not ConfigurationSettingsType Is Nothing Then
                smSerializer = New XmlSerializer(ConfigurationSettingsType)
            End If

            If Not smSerializer Is Nothing Then
                Dim reader As StreamReader
                Try
                    reader = New StreamReader("current_settings.xml")
                    Dim settings As ManagerFormSettings = DirectCast(smSerializer.Deserialize(reader), ManagerFormSettings)
                    BindFromSettingsToSelf(settings)
                Catch ex As FileNotFoundException
                    ' Swallow this one
                Finally
                    If Not reader Is Nothing Then reader.Close()
                End Try
            End If

            With MessageGrid
                .Font = GlobalUISettings.Defaults.Fonts.Small
                .ColCount = 2
                .Width = Width - LeftPanel.Width
                .ColWidths(1) = 100
                .ColWidths(2) = .Width - .ColWidths(1)

                ' Fade the colors from bottom to top
                Dim colorStep As Integer = CInt(255 / (.RowCount))
                For i As Integer = 1 To MessageGrid.RowCount
                    Dim grey As Integer = CInt((MessageGrid.RowCount - i) * colorStep)
                    .RowStyles(i).TextColor = Color.FromArgb(grey, grey, grey)
                Next

            End With

            Text = ManagerName

            ' Name label
            NameLabel.Text = "  " & ManagerName
            NameLabel.BackgroundColor = _
                New Syncfusion.Drawing.BrushInfo(Syncfusion.Drawing.GradientStyle.BackwardDiagonal, SecondaryLabelColor, SystemColors.Window)


        End Sub

        Protected Sub ShowMessage(ByVal message As String)
            MessageGrid.BeginUpdate()
            For i As Integer = 1 To MessageGrid.RowCount - 1
                MessageGrid(i, 1).Text = MessageGrid(i + 1, 1).Text
                MessageGrid(i, 2).Text = MessageGrid(i + 1, 2).Text
            Next
            MessageGrid(MessageGrid.RowCount, 1).Text = DateTime.Now.ToLongTimeString
            MessageGrid(MessageGrid.RowCount, 2).Text = message
            MessageGrid.EndUpdate()
        End Sub

        Protected Overrides Sub OnClosing(ByVal e As CancelEventArgs)

            If Not mCoordinator Is Nothing Then
                Try
                    If Not mImportantStateChangeWrapper Is Nothing Then mImportantStateChangeWrapper.StopListening()
                    If Not mManagerArrivalOrDepartureWrapper Is Nothing Then mManagerArrivalOrDepartureWrapper.StopListening()
                    If Not mBiographicFormChangeWrapper Is Nothing Then mBiographicFormChangeWrapper.StopListening()

                    ' Only depart if we're not already connected
                    If Not mIsAlreadyConnected Then mCoordinator.Depart(Hostname, Category)
                Catch ex As Net.WebException ' Do nothing
                Catch ex As Belikov.GenuineChannels.OperationException
                Catch ex As Net.Sockets.SocketException ' Do nothing
                End Try
            End If

            If Not ConfigurationSettingsType Is Nothing Then
                SaveCurrentSettings(DirectCast(Activator.CreateInstance(ConfigurationSettingsType), ManagerFormSettings))
            End If

            MyBase.OnClosing(e)

        End Sub

        Public Sub SaveCurrentSettings(ByVal settings As ManagerFormSettings)
            Dim sw As StreamWriter
            Try
                BindFromSelfToSettings(settings)
                sw = New StreamWriter("current_settings.xml")
                smSerializer.Serialize(sw, settings)
            Catch ex As Exception
                Mbark.UI.PrettyPrintException(ex)
            Finally
                sw.Close()
            End Try

        End Sub


        Protected Overridable ReadOnly Property ConfigurationSettingsType() As Type
            Get

            End Get
        End Property

        Protected Overridable Sub BindFromSettingsToSelf(ByVal s As ManagerFormSettings)

        End Sub

        Protected Overridable Sub BindFromSelfToSettings(ByVal s As ManagerFormSettings)

        End Sub

        Protected ReadOnly Property Coordinator() As ISystemCoordinator
            Get
                Return mCoordinator
            End Get
        End Property


#Region "  Start Coordination  "

        Protected Enum StartCoordinationResult
            CoordinatorFound
            NoCoordinatorFound
            AlreadyInProgress
            ManagerIsClosing
        End Enum

        Private mCoordinator As ISystemCoordinator
        Private WithEvents mStartCoordinationTimer As New Timers.Timer(SystemCoordinator.ClientKeepAliveFrequency)

        Private mInsideStartCoordination As Boolean
        Protected Function StartCoordination() As StartCoordinationResult

            Try

                ' Don't try to connect if the manager is closing
                If MyBase.IsClosing Then Return StartCoordinationResult.ManagerIsClosing

                ' Prevent reentry
                If mInsideStartCoordination Then Return StartCoordinationResult.AlreadyInProgress

                mInsideStartCoordination = True

                ' Populate the remote objects
                mCoordinator = DirectCast(GetObject(GetType(ISystemCoordinator)), ISystemCoordinator)

                ' Establish an explicit connection with the coordinator
                mCoordinator.Arrive(Hostname, Category)

                ' Be notified of manager arrivals/departures
                mManagerArrivalOrDepartureWrapper = New RemotingEventWrapper(mCoordinator.ManagerArrivalOrDeparture)
                mImportantStateChangeWrapper = New RemotingEventWrapper(mCoordinator.ImportantStateChange)
                mBiographicFormChangeWrapper = New RemotingEventWrapper(mCoordinator.BiographicFormChange)

                AddHandler _
                    mManagerArrivalOrDepartureWrapper.RemotingEventArrivedLocally, _
                    AddressOf mManagerArrivalOrDepartureWrapper_RemotingEventArrivedLocally
                AddHandler _
                    mImportantStateChangeWrapper.RemotingEventArrivedLocally, _
                    AddressOf mImportantStateChangeWrapper_RemotingEventArrivedLocally
                AddHandler _
                    mBiographicFormChangeWrapper.RemotingEventArrivedLocally, _
                    AddressOf mBiographicFormChangeWrapper_RemotingEventArrivedLocally

                ' With a connection established, we no longer have to try to start the connection
                mStartCoordinationTimer.Stop()

                ' Let child classes do something on an override
                OnCoordinationStarted()

                KeepAliveTimer.Enabled = True

                Return StartCoordinationResult.CoordinatorFound

            Catch ex As NoSuchWellKnownClientTypeException
                'ShowMessage("Likely problem in configuration file")

            Catch ex As Net.WebException

                KeepAliveTimer.Enabled = False
                If Not mStartCoordinationTimer.Enabled Then mStartCoordinationTimer.Start()
                Return StartCoordinationResult.NoCoordinatorFound

            Catch ex As Net.Sockets.SocketException

                KeepAliveTimer.Enabled = False
                If Not mStartCoordinationTimer.Enabled Then mStartCoordinationTimer.Start()
                Return StartCoordinationResult.NoCoordinatorFound

            Catch ex As Belikov.GenuineChannels.OperationException
                KeepAliveTimer.Enabled = False
                If Not mStartCoordinationTimer.Enabled Then mStartCoordinationTimer.Start()
                Return StartCoordinationResult.NoCoordinatorFound
            Finally
                mInsideStartCoordination = False
            End Try

        End Function

        Private Sub mStartCoordinationTimer_Elapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) _
        Handles mStartCoordinationTimer.Elapsed
            OnStartCoordinationTimerElapsed()

            ' Everytime the timer elapses, try to start the coordination again (if we're not already doing it)
            If Not mInsideStartCoordination Then
            ChangeState(StartCoordinationState, UI.FormStateChangeTrigger.EventActivated, "mStartCoordinationTimer_Elapsed", Nothing)
            End If
        End Sub

        Protected Overridable Sub OnStartCoordinationTimerElapsed()
        End Sub

        Protected Overridable Sub OnCoordinationStarted()

        End Sub

        Private WithEvents mManagerArrivalOrDepartureWrapper As RemotingEventWrapper
        Private Sub mManagerArrivalOrDepartureWrapper_RemotingEventArrivedLocally(ByVal originatingHostname As String, ByVal e As EventArgs)

            ' Let the child manager handle the event
            OnManagerArrivalOrDeparture(originatingHostname, DirectCast(e, ManagerArrivalOrDepartureEventArgs))

            ' If we're awaiting a particular manager, then we need to reneter the same state. We don't need to check
            ' all of the details because the state transition itself will do this for us (i.e., the child will call
            ' AwaitManager(), which has all of the appropriate logic.
            '
            If mAwaitingManager AndAlso (mAwaitingManagerArrival OrElse mAwaitingManagerDeparture) Then
                ChangeState( _
                    CurrentFormState, _
                    FormStateChangeTrigger.EventActivated, _
                    "mManagerArrivalOrDepartureWrapper_RemotingEventArrivedLocally", _
                    Nothing)
            End If

        End Sub

        Private WithEvents mImportantStateChangeWrapper As RemotingEventWrapper
        Private Sub mImportantStateChangeWrapper_RemotingEventArrivedLocally(ByVal originatingHostname As String, ByVal e As EventArgs)

            OnImportantStateChange(originatingHostname, e)

            If mAwaitingManager AndAlso mAwaitingParticularState Then
                ChangeState( _
                    CurrentFormState, _
                    FormStateChangeTrigger.EventActivated, _
                    "mImportantStateChangeWrapper_RemotingEventArrivedLocally", _
                    Nothing)
            End If
        End Sub

        Private WithEvents mBiographicFormChangeWrapper As RemotingEventWrapper
        Private Sub mBiographicFormChangeWrapper_RemotingEventArrivedLocally(ByVal originalHostname As String, ByVal e As EventArgs)
            OnBiographicFormChange(originalHostname, DirectCast(e, BiographicFormChangedEventArgs))
        End Sub

        Protected Overridable Sub OnManagerArrivalOrDeparture(ByVal originatingHostname As String, ByVal e As ManagerArrivalOrDepartureEventArgs)

        End Sub

        Protected Overridable Sub OnImportantStateChange(ByVal originatingHostname As String, ByVal e As EventArgs)

        End Sub

        Protected Overridable Sub OnBiographicFormChange(ByVal originatingHostname As String, ByVal e As BiographicFormChangedEventArgs)

        End Sub

#End Region

#Region "  Keep Alive  "

        Private WithEvents mKeepAliveTimer As New Timers.Timer(SystemCoordinator.ClientKeepAliveFrequency)
        Private mInsideKeepAlive As Boolean
        Protected ReadOnly Property KeepAliveTimer() As Timers.Timer
            Get
                Return mKeepAliveTimer
            End Get
        End Property


        Private Sub mKeepAliveTimer_Elasepd(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) _
        Handles mKeepAliveTimer.Elapsed
            KeepAlive()
        End Sub

        Protected Sub KeepAlive()
            If MyBase.IsClosing OrElse mInsideKeepAlive Then Return
            mInsideKeepAlive = True

            Try
                If Not mCoordinator Is Nothing Then
                    mCoordinator.KeepAlive(Hostname, Category, CurrentFormState)
                End If
            Catch ex As Belikov.GenuineChannels.OperationException
                OnUnexpectedDisconnection(Hostname, Category)
                'Console.WriteLine("Server not alive")
            Catch ex As Exception
                Debugger.Break()
            Finally
                mInsideKeepAlive = False
            End Try
        End Sub

#End Region
        Protected Overridable Sub OnUnexpectedDisconnection(ByVal hostname As String, ByVal cateogory As ManagerCategory)
            mKeepAliveTimer.Enabled = False
        End Sub
        Protected DefaultRetryFrequency As Double = 1000

#Region "  Await Valid Deployment  "

        Private mSelectedDeploymentProvider As ISelectedDeploymentProvider
        Private mSelectedDeploymentChanged As RemotingEventWrapper

        Protected ReadOnly Property SelectedDeployment() As DeploymentEntity
            Get
                If mSelectedDeploymentProvider Is Nothing Then Return Nothing
                Return mSelectedDeploymentProvider.SelectedDeployment()
            End Get
        End Property

        Protected Enum AwaitValidDeploymentResult
            GotValidDeployment
            NoValidDeployment
            LostConnection
        End Enum

        Private WithEvents mAwaitValidDeploymentTimer As New Timers.Timer(DefaultRetryFrequency)


        Protected Function AwaitValidDeployment() As AwaitValidDeploymentResult
            Try
                ' Get a deployment provider
                mSelectedDeploymentProvider = DirectCast(GetObject(GetType(ISelectedDeploymentProvider)), ISelectedDeploymentProvider)

                ' Subscribe to changes in the selected deployment
                mSelectedDeploymentChanged = New RemotingEventWrapper(mSelectedDeploymentProvider.SelectedDeploymentChanged)
                AddHandler _
                    mSelectedDeploymentChanged.RemotingEventArrivedLocally, _
                    AddressOf mSelectedDeploymentChanged_RemotingEventArrivedLocally

                mAwaitValidDeploymentTimer.Enabled = False
                If SelectedDeployment Is Nothing Then
                    Return AwaitValidDeploymentResult.NoValidDeployment
                Else
                    ' FIXME: Validate dates of deployment?
                    Return AwaitValidDeploymentResult.GotValidDeployment
                End If

            Catch ex As Net.WebException
                mAwaitValidDeploymentTimer.Enabled = True
                Return AwaitValidDeploymentResult.LostConnection
            End Try
        End Function


        Private Sub mSelectedDeploymentChanged_RemotingEventArrivedLocally(ByVal originatingHostname As String, ByVal e As EventArgs)
            OnSelectedDeploymentChanged()
        End Sub

        Protected Overridable Sub OnSelectedDeploymentChanged()

        End Sub

#End Region

#Region "  Await Manager  "

        Protected Enum AwaitManagerReuslt
            ManagerArrived
            ManagerDeparted
            FalseAlarm
            LostConnection
        End Enum

        Protected Function AwaitArrival(ByVal hostnameToWaitFor As String, ByVal categoryToWaitFor As ManagerCategory) _
        As AwaitManagerReuslt
            Return AwaitManager(True, False, False, -1, hostnameToWaitFor, categoryToWaitFor)
        End Function


        Private mAwaitingManager As Boolean
        Private mAwaitingManagerArrival As Boolean
        Private mAwaitingManagerDeparture As Boolean
        Private mAwaitingParticularState As Boolean

        Private mDesiredStateOfManagerToWaitUpon As Integer
        'Private mHostnameOfManagerWaitingUpon As String
        'Private mCategoryOfManagerWaitingUpon As ManagerCategory
        Private WithEvents mAwaitManagerTimer As New Timers.Timer(DefaultRetryFrequency)


        Private Function AwaitManager( _
            ByVal waitForArrival As Boolean, _
            ByVal waitForDeparture As Boolean, _
            ByVal waitForParticularState As Boolean, _
            ByVal stateToWaitFor As Integer, _
            ByVal hostnameToWaitFor As String, _
            ByVal categoryToWaitFor As ManagerCategory) As AwaitManagerReuslt

            ' First, keep track of the fact that we're really waiting for a manager
            mAwaitingManager = True

            mAwaitingManagerArrival = waitForArrival
            mAwaitingManagerDeparture = waitForDeparture
            mAwaitingParticularState = waitForParticularState


            Try
                mAwaitManagerTimer.Enabled = True
                If waitForArrival AndAlso mCoordinator.IsAlive(hostnameToWaitFor, categoryToWaitFor) Then
                    Return AwaitManagerReuslt.ManagerArrived
                End If

                If waitForDeparture AndAlso Not mCoordinator.IsAlive(hostnameToWaitFor, categoryToWaitFor) Then
                    Return AwaitManagerReuslt.ManagerDeparted
                End If

                Return AwaitManagerReuslt.FalseAlarm

            Catch ex As Net.WebException
                mAwaitManagerTimer.Enabled = True
                Return AwaitManagerReuslt.LostConnection
            End Try

        End Function

        Protected Sub StopWaiting()
            mAwaitingManager = False
            mAwaitManagerTimer.Enabled = False
        End Sub

        Private Sub mAwaitManagerTimer_Elasped(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) _
        Handles mAwaitManagerTimer.Elapsed
            If mAwaitingManager Then
                ' Trigger a refresh of the current state
                ChangeState(CurrentFormState, FormStateChangeTrigger.EventActivated, "mAwaitManagerTimer_Elapsed", Nothing)
            End If
        End Sub

        Protected Overridable Sub OnAwaitManagerSuccess( _
            ByVal wasWaitingForArrival As Boolean, _
            ByVal wasWaitingForDeparture As Boolean, _
            ByVal wasWaitingForParticularState As Boolean, _
            ByVal desiredStateOfManager As Integer, _
            ByVal hostnameOfManager As String, _
            ByVal desiredCategoryOfManager As ManagerCategory)

        End Sub





#End Region

        Private mStateToEnterAfterCoordinationStarted As Integer = -1
        Protected Property StateToEnterAfterCoordinationStarted() As Integer
            Get
                Return mStateToEnterAfterCoordinationStarted
            End Get
            Set(ByVal value As Integer)
                mStateToEnterAfterCoordinationStarted = value
            End Set
        End Property

        Public ReadOnly Property Hostname() As String
            Get
                Return Net.Dns.GetHostName
            End Get
        End Property

        Public Overridable ReadOnly Property Category() As ManagerCategory
            Get
                Throw New MissingSpecializationException(Me.GetType(), "Category")
            End Get
        End Property
        Public Overridable ReadOnly Property StartCoordinationState() As Integer
            Get

            End Get
        End Property
        Public Overridable ReadOnly Property ManagerName() As String
            Get

            End Get
        End Property
        Public Overridable ReadOnly Property SecondaryLabelColor() As Color
            Get

            End Get
        End Property

        Private Sub MinimizeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MinimizeButton.Click
            WindowState = FormWindowState.Minimized
        End Sub

        Private Sub CloseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CloseButton.Click
            Me.Close()
        End Sub

        Private mIsAlreadyConnected As Boolean
        Public ReadOnly Property IsAlreadyConnected() As Boolean
            Get
                Return mIsAlreadyConnected
            End Get
        End Property

        Protected Sub AlreadyConnectedShutdown()
            mIsAlreadyConnected = True
            Me.Close()
            MsgBox("Already connected. Try again in a little bit.")
            Application.Exit()
        End Sub

    End Class

    Public MustInherit Class ManagerFormSettings

    End Class


End Namespace
