' Gambas module file

' TODO: Make real setup for playing
' TODO: There is an occasional flickering when shooting and the ships are already near the player and few

Public X As Integer
Public Y As Integer
' Hardcoded corresponding to the strings in Draw() below!
Public Width As Integer = 3
Public Height As Integer = 2

Private $hEnemies As Timer
Private $hMissiles As Timer

Public Sub Main()
  ' Debug aid. Watch /tmp/pipe with "tail -f"
  ' Dim hPipe As Stream
  ' 
  ' hPipe = Pipe "/tmp/pipe" For Write
  ' Error To #hPipe

  Screen.Cursor = Cursor.Hidden
  Screen.Echo = False
  Window.Attributes = Attr.Bold
  Object.Attach(Window, Me, "Window")
  Window.SetFocus()

  X = (Window.Width - Width) \ 2
  Y = Window.Height - Height

  Object.Attach(Enemies, Me, "Enemies")

  Draw()
  ' Populate ca. 1/3 of the screen with enemies. It will actually look more
  ' because of the enemy arrangement. But that's good :-)
  Enemies.Init(Window, Window.Width * Window.Height / 3 / Enemy.AverageWidth)
  Missiles.Init(Window)
  Window.Buffered = True

  $hEnemies = New Timer As "Enemies"
  ' TODO: The Timers are made for a 80*24 terminal.
  ' Make it 100 and you'll likely win, 75 really depends on the amount of Borg for me...
  $hEnemies.Delay = 75
  $hMissiles = New Timer As "Missiles"
  $hMissiles.Delay = 50

  $hEnemies.Start()
  $hMissiles.Start()
End

Public Sub Window_Read()
  Select Window.Read()
    ' Navigate left/right
    Case Key.Left
      If X = 0 Then Return
      Undraw()
      Dec X
      Draw()
    Case Key.Right
      If X + Width >= Window.Width Then Return
      Undraw()
      Inc X
      Draw()
    ' Navigate up/down
    Case Key.Up
      If Y <= 0 Then Return
      Undraw()
      Dec Y
      Draw()
    Case Key.Down
      If Y >= Window.Height - Height Then Return
      Undraw()
      Inc Y
      Draw()
    ' Shoot normal missile
    Case Key[" "]
      Missiles.Shoot(Missile.Normal, X, Y - 1)
      'If Not $hMissiles.Enabled Then $hMissiles.Start()
    ' Shoot super missile
    Case Key["v"]
      Missiles.Shoot(Missile.Super, X, Y - 1)
      'If Not $hMissiles.Enabled Then $hMissiles.Start
    ' Of course, manipulate the timers
    Case Key["+"]
      $hEnemies.Delay -= 10
      $hMissiles.Delay -= 5
    Case Key["-"]
      $hEnemies.Delay += 10
      $hMissiles.Delay += 5
  End Select
End

Public Sub Enemies_Triumph()
  End("TRIUMPH!", Color.Yellow)
End

Public Sub Enemies_GameOver()
  End("GAME OVER!", Color.Blue)
End

Private Sub End(sMessage As String, iColor As Integer)
  $hEnemies.Stop()
  $hMissiles.Stop()
  '' TODO: The message display is glitchy
  Window.Buffered = False
  Window.PrintCenter(sMessage,, Pair[iColor, Window.Background])
  '' TODO: What now? Note that the user can still interact at this point...
End

Private Sub Draw()
  Window.Print(" | ", X, Y)
  Window.Print("^'^", X, Y + 1)
End

Private Sub Undraw()
  Window.Print(Space$(Width), X, Y)
  Window.Print(Space$(Width), X, Y + 1)
End

Public Sub Enemies_Timer()
  Enemies.Move()
  If Not $hMissiles.Enabled Then
    Enemies.Draw()
    Screen.Refresh()
  Endif
End

Public Sub Missiles_Timer()
  If Missiles.Move() And Missiles.Count = 0 Then
    '$hMissiles.Stop()
    Return
  Endif
  ' Missiles draw at a higher rate so we can safely redraw everything
  ' here. Note that, thanks to ncurses' buffering, only the changed
  ' parts are redrawn so that there is no overhead in more frequent
  ' Screen.Refresh()es here.
  Enemies.Draw()
  Screen.Refresh()
End
