
--
-- Copyright (C) 2020  <fastrgv@gmail.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You may read the full text of the GNU General Public License
-- at <http://www.gnu.org/licenses/>.
--





with tput00_h;


with Text_IO;
with SysUtils;  use SysUtils;
with ada.directories;
with Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO;
with ada.characters.handling;
with gnat.os_lib;
with realtime_hpp;
with interfaces.c;
use type interfaces.c.int;
with interfaces.c.strings;

with GNATCOLL.Terminal;  use GNATCOLL.Terminal;





procedure nexus is

use Ada.Strings.Unbounded;
use Ada.Strings.Unbounded.Text_IO;
use ada.directories;
use text_io;


	mswin: constant boolean := (gnat.os_lib.directory_separator='\');



	search : search_type;
	directory_entry : directory_entry_type;


	type linearray is array(1..13) of string(1..80);
	line: linearray;


	ch: character;

	erase,changed, userselect,
	userexit, help, Ok, winner, playedonce : boolean := false;


	infilname : unbounded_string;


	epsilon : constant float := 0.01;

	selLine: integer:=1;


--useUpDir: boolean := false;
	updir : string := "../../";








	package myint_io is new text_io.integer_io(integer);
	package myfloat_io is new text_io.float_io(float);




procedure myassert( condition : boolean;  flag: integer:=0 ) is
begin
  if condition=false then
  		put("ASSERTION Failed!  ");
		if flag /= 0 then
			put_line( "@ " & integer'image(flag) );
		end if;
		new_line;
  		raise program_error;
  end if;
end myassert;





procedure init is
	fname : string := "puzzles.txt";
	fileid : text_io.file_type;
	len: natural;
begin

	--useUpDir:=false;

	--note:  if user calls this executable from the directory in
	--       which it resides, we need to adjust the path thusly:
	--if ada.directories.exists(fname) then
	--	text_io.Open
	--		(File => FileId,
	--		 Mode => text_io.In_File,
	--		 Name => fname);
	--else
		--useUpDir:=true;
	--	text_io.Open
	--		(File => FileId,
	--		 Mode => text_io.In_File,
	--		 Name => updir&fname);
	--end if;



-- FTTB this MUST be run in local directory:

	text_io.Open
		(File => FileId,
		 Mode => text_io.In_File,
		 Name => updir&fname);

	line := (others=>(others=>' '));
	for i in 1..13 loop

		text_io.get_line(fileid, line(i), len);

	end loop;

   text_io.Close (File => FileId);

	selLine:=1;

end init;















procedure Draw is
	info: terminal_info;
	Ok: boolean;
	--ch: character;
begin

	info.init_for_stdout(auto);


	if mswin then
		--SysUtils.bShell("cls", Ok); -- erase-terminal
		tput00_h.cursorHome;
	else
		SysUtils.bShell("tput cup 0 0", Ok); -- erase-terminal
	end if;


	--put_line(objectiveText);
	put_line("Use arrow keys to move Up or Down");
	put_line(" s-key to select;  q = quit");
	new_line;




-- colors available:
-- black,red,green,yellow,blue,magenta,cyan,grey
	Info.Set_Color (background=>black);
	Info.Set_Color (foreground=>blue);



	for row in 1..13 loop

		if row=selLine then
			Info.Set_Color (foreground=>blue);
		else
			Info.Set_Color (foreground=>magenta);
		end if;

		put( line(row) );

		Info.Set_Color (foreground=>blue);
		new_line;
	end loop;

	Info.Set_Color (foreground=>blue);


   Info.Set_Color (Standard_Output, Style => Reset_All);


end Draw;










procedure handle_key_down( ch: character ) is
begin


-- note that arrow keys typically produce chars
-- preceded by 1 or 2 non-printable chars.
--
-- on Linux:		<home>='H'	<end>='F'
--   A		
-- D B C
--
-- or on MSWin:	<home>='G'	<end>='O'
--   H
-- K P M


if ada.characters.handling.is_letter(ch) or (ch='?') then

	changed:=true;
	case ch is

		when 'x' | 'q' =>	userexit:=true;

		when 'H' | 'A' =>	--Up
			selLine:=selLine-1;
			if selLine=0 then selLine:=13; end if;

		when 'P' | 'B' =>	--Dn
			selLine:=selLine+1;
			if selLine>13 then selLine:=1; end if;

		when 's' => --select this one
			userselect:=true;

		when others => changed:=false;

	end case;

end if;
end handle_key_down;












	rtime: interfaces.c.int;




begin --nexus


	if mswin then
		rtime:=realtime_hpp.hiPriority;
		-- note:  this seems necessary because some, 
		-- but not all, windows commandline terminals 
		-- seem to randomly freeze at normal priority.
	else
		rtime:=1;
	end if;





	Init; --// define puzzle parameters here



	if mswin then
		SysUtils.bShell("cls", Ok); -- erase-terminal
	else
		SysUtils.bShell("clear", Ok); -- erase-terminal
	end if;



	changed:=true;
	Draw;
	while not userexit loop
		get_immediate(ch);
		handle_key_down( ch );

		if userselect then


			case selLine is
				when 1 =>
					SysUtils.bShell("c7", Ok);
				when 2 =>
					SysUtils.bShell("c9", Ok);
				when 3 =>
					SysUtils.bShell("caz", Ok);
				when 4 =>
					SysUtils.bShell("cdd", Ok);
				when 5 =>
					SysUtils.bShell("chio", Ok);
				when 6 =>
					SysUtils.bShell("chio4", Ok);
				when 7 =>
					SysUtils.bShell("cpana", Ok);
				when 8 =>
					SysUtils.bShell("crush", Ok);
				when 9 =>
					SysUtils.bShell("cslid", Ok);
				when 10 =>
					SysUtils.bShell("csok", Ok);

				when 11 =>
					SysUtils.bShell("rpn", Ok);
				when 12 =>
					SysUtils.bShell("cfrog", Ok);
				when 13 =>
					SysUtils.bShell("cpac", Ok);

				when others => null;
			end case;

			userselect:=false;
		end if;

		Draw;
	end loop;



	if mswin then
		SysUtils.bShell("cls", Ok); -- erase-terminal
	else
		SysUtils.bShell("clear", Ok); -- erase-terminal
	end if;



end nexus;

