
Public Class WallBlock
    Inherits Block

    Private _NorthFacingPicture As Picture
    Private _SouthFacingPicture As Picture
    Private _EastFacingPicture As Picture
    Private _WestFacingPicture As Picture
    Private _PicturesVisible As Boolean

    Public Property MapPositionX As Integer
    Public Property MapPositionZ As Integer

    Sub New(game As Game, world As VirtualWorld, position As Vector3, rotation As Vector3, texture As Texture2D, shape As Cube, effect As BasicEffect)
        MyBase.new(game, world, position, rotation, texture, shape, effect)
    End Sub

    Sub New(game As Game, world As VirtualWorld, position As Vector3, rotation As Vector3, color As System.Drawing.Color, shape As Cube, effect As BasicEffect)
        MyBase.New(game, world, position, rotation, color, shape, effect)
    End Sub

    Public Function GetPictures() As List(Of Picture)
        Dim l As New List(Of Picture)
        l.Add(Me.SouthFacingPicture)
        l.Add(Me.NorthFacingPicture)
        l.Add(Me.EastFacingPicture)
        l.Add(Me.WestFacingPicture)
        Return l.FindAll(Function(o) Not o Is Nothing)
    End Function

    Public Property PicturesVisible As Boolean
        Get
            Return Me._PicturesVisible
        End Get
        Set(value As Boolean)
            Me._PicturesVisible = value
            Me.GetPictures.ForEach(Sub(o) o.Visible = value)
        End Set
    End Property

    Public ReadOnly Property AdjacentNorthWallBlock As WallBlock
        Get
            Return Me.World.GetWallBlockByMapPosition(Me.MapPositionX, Me.MapPositionZ + 1)
        End Get
    End Property

    Public ReadOnly Property AdjacentSouthWallBlock As WallBlock
        Get
            Return Me.World.GetWallBlockByMapPosition(Me.MapPositionX, Me.MapPositionZ - 1)
        End Get
    End Property

    Public ReadOnly Property AdjacentEastWallBlock As WallBlock
        Get
            Return Me.World.GetWallBlockByMapPosition(Me.MapPositionX + 1, Me.MapPositionZ)
        End Get
    End Property

    Public ReadOnly Property AdjacentWestWallBlock As WallBlock
        Get
            Return Me.World.GetWallBlockByMapPosition(Me.MapPositionX - 1, Me.MapPositionZ)
        End Get
    End Property

    Public Function HasFreeFaces() As Boolean
        Return Me.GetFreeFaces.Count > 0
    End Function

    Public Function GetFreeFaces() As List(Of FaceDirection)
        ' selects a free face direction at random
        Dim l As New List(Of FaceDirection)
        If Me.SouthFacingPicture Is Nothing And _
            Me.IsPerimeterBlock(FaceDirection.South) = False _
            And Me.AdjacentSouthWallBlock Is Nothing Then l.Add(FaceDirection.South)
        If Me.NorthFacingPicture Is Nothing And _
            Me.IsPerimeterBlock(FaceDirection.North) = False _
            And Me.AdjacentNorthWallBlock Is Nothing Then l.Add(FaceDirection.North)
        If Me.EastFacingPicture Is Nothing And _
            Me.IsPerimeterBlock(FaceDirection.East) = False _
            And Me.AdjacentEastWallBlock Is Nothing Then l.Add(FaceDirection.East)
        If Me.WestFacingPicture Is Nothing And _
            Me.IsPerimeterBlock(FaceDirection.West) = False _
            And Me.AdjacentWestWallBlock Is Nothing Then l.Add(FaceDirection.West)
        Return l
    End Function

    Public Function HasOpenFaces() As Boolean
        Return Me.GetOpenFaces.Count > 0
    End Function

    Public Function GetOpenFaces() As List(Of FaceDirection)
        Dim l As New List(Of FaceDirection)
        If Me.AdjacentSouthWallBlock Is Nothing Then l.Add(FaceDirection.South)
        If Me.AdjacentNorthWallBlock Is Nothing Then l.Add(FaceDirection.North)
        If Me.AdjacentEastWallBlock Is Nothing Then l.Add(FaceDirection.East)
        If Me.AdjacentWestWallBlock Is Nothing Then l.Add(FaceDirection.West)
        Return l
    End Function

    Public Sub AttachPictureToFace(picture As Picture, faceDirection As FaceDirection)
        Select Case faceDirection
            Case faceDirection.South
                'no rotation required
                'move to face
                picture.Position = New Vector3(Me.Position.X, Me.Position.Y, Me.Position.Z - CSng((Me.Size.Z / 2) + 0.1))
                Me._SouthFacingPicture = picture
            Case faceDirection.North
                picture.RotationY = 180
                picture.Position = New Vector3(Me.Position.X, Me.Position.Y, Me.Position.Z + CSng((Me.Size.Z / 2) + 0.1))
                Me._NorthFacingPicture = picture
            Case faceDirection.East
                picture.RotationY = 270
                Dim xPos As Single = Me.Position.X + CSng((Me.Size.X / 2) + 0.1)
                picture.Position = New Vector3(xPos, Me.Position.Y, Me.Position.Z)
                Me._EastFacingPicture = picture
            Case faceDirection.West
                picture.RotationY = 90
                Dim xPos As Single = Me.Position.X - CSng((Me.Size.X / 2) + 0.1)
                picture.Position = New Vector3(xPos, Me.Position.Y, Me.Position.Z)
                Me._WestFacingPicture = picture
        End Select
    End Sub

    Public Function SelectFreeFaceAtRandom(r As Random) As FaceDirection
        Dim l As List(Of FaceDirection) = Me.GetFreeFaces
        If l.Count = 0 Then Return Nothing
        Return (l.Item(r.Next(0, l.Count - 1)))
    End Function

    Public Function IsPerimeterBlock(faceDirection As FaceDirection) As Boolean
        Select Case faceDirection
            Case faceDirection.South
                If Me.MapPositionZ - 1 < 0 Then Return True
            Case faceDirection.North
                If Me.MapPositionZ + 1 = Me.World.WorldLengthUnits Then Return True
            Case faceDirection.East
                If Me.MapPositionX + 1 = Me.World.WorldWidthUnits Then Return True
            Case faceDirection.West
                If Me.MapPositionX - 1 < 0 Then Return True
        End Select
        Return False
    End Function

    Public Function IsPerimeterBlock() As Boolean
        Dim l As New List(Of Boolean)
        l.Add(Me.IsPerimeterBlock(FaceDirection.South))
        l.Add(Me.IsPerimeterBlock(FaceDirection.North))
        l.Add(Me.IsPerimeterBlock(FaceDirection.East))
        l.Add(Me.IsPerimeterBlock(FaceDirection.West))
        Return l.Contains(True)
    End Function

    Public ReadOnly Property NorthFacingPicture As Picture
        Get
            Return Me._NorthFacingPicture
        End Get
    End Property

    Public ReadOnly Property SouthFacingPicture As Picture
        Get
            Return Me._SouthFacingPicture
        End Get
    End Property

    Public ReadOnly Property EastFacingPicture As Picture
        Get
            Return Me._EastFacingPicture
        End Get
    End Property

    Public ReadOnly Property WestFacingPicture As Picture
        Get
            Return Me._WestFacingPicture
        End Get
    End Property

End Class