#!/usr/bin/env BQN
# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 Rampoina <rampoina@protonmail.com>

⟨ansi⟩←•Import "ansi.bqn"
⟨Game⟩←•Import "logic.bqn"

opts←{
  a←•args
  _optl_←{≠◶⟨𝔾,𝔽⊑⟩ (»a∊𝕩)/a}
  _opt_←{ 𝔽_optl_𝔾 ⋈𝕩}
  {𝕤
    •Out "Usage: "∾•name∾" [OPTION]...
  -h,--help
         Displays a help message

  -l,--levels FILE
         Load levels from FILE.  (default: a file called “levels”).

  -c,--chars string
         Characters to display for each game object, needs to have length 15.  (default: ” λ$⊕⭍#/-|+<>^v”).

  -f,--fchars string
         Characters to represent each game object in the levels file, needs to have length 15.  (default: ” @$o⭍#/-|+<>^v”).

  -s,--start N
              Start directly at level number N.  (default: 1)."
    •Exit 0
  }⍟∨´"-h"‿"--help"∊a

  chars ⇐ ⊢_optl_" λ$⊕⭍#/\-|+<>^v" "-c"‿"--chars"
  fchars⇐ ⊢_optl_" @$o⭍#/\-|+<>^v" "-f"‿"--fchars"
  levels⇐ ⊢_optl_"levels"          "-l"‿"--levels"
  n⇐{1⌈•BQN⎊{𝕊: •Out "Invalid starting level number" ⋄ •Exit 1} 𝕩}_optl_ 1 "-s"‿"--start"
}

g←Game⎊{𝕊: •Out •CurrentError @ ⋄ •Exit 1} opts.n‿opts.levels‿opts.chars‿opts.fchars‿⟨ansi.defaultB,ansi.yellow,ansi.cyan,ansi.red⟩
ansi.InitTerm @
clear←""
{𝕤 # Loop until the user wins
  •Out clear∾ansi.cursor.origin
  clear↩""
  •Out "Level: "∾•Repr 1+g.currentLevel
  •Out (g.Color g.pmachine)∾ansi.defaultB∾" Power the machines ("∾(g.Color g.machine)∾") by moving the mirrors ("∾(∾g.Color¨ g.mirrors)∾ansi.defaultB∾")"
  •Out "Controls: (hjkl or wasd) to move, u to undo, r to reset level, q to quit"
  g.Draw @
  •Out "Moves: "∾•Repr ¯1+≠g.moves
  g.WinLevel @ ?
    •Out "Good job!, press any key to continue to the next level"
    key←•term.CharB @
    clear↩ansi.clear.screen
    g.NextLevel @
    {𝕤⋄ansi.RestoreTerm @⋄•Exit 0}⍟(key='q')@
    ;
    key←•term.CharB @
    {𝕤⋄g.Next ⊑("hjklaswd"=key)/∾˜⟨0‿¯1,1‿0,¯1‿0,0‿1⟩}⍟(⊑key∊"hjklaswd")@
    {𝕤⋄clear↩""‿ansi.clear.screen⊑˜((1⊸+>○(≠•Repr)⊢)¯1+≠g.moves)⋄g.Undo @}⍟(key='u')@
    {𝕤⋄ansi.RestoreTerm @⋄•Exit 0}⍟(key='q')@
    {𝕤⋄clear↩ansi.clear.screen⋄g.Reset @}⍟(key='r')@
}•_While_{𝕤⋄g.Over @}@
•Out "Well played, you win!"
ansi.RestoreTerm @
