/*
//---------------- set of system functions to use in a final (compiled) project
// This file should be copied to the destination directory if it is necessary.
// To do so, use an option /copy System_functions.cs (source directory should
// be listed with /src option).

CLASS {System_functions|_Android},
	NATIVE, UNTESTED, STOPPING, BYTES,
	ABSTRACT :

IMPORT: {String_functions} ;

NATIVE: "import java.net.InetAddress;" .
NATIVE: "import android.content.pm.ApplicationInfo;" .
NATIVE: "import java.io.File;" .
NATIVE: "import android.media.ToneGenerator;" .
NATIVE: "import android.media.AudioManager;" .

NATIVE: "///copy System_functions.java" .

*/
	import java.util.ArrayList;

    public class System_functions
    {

        /*
        
        FUN Platform_info|rmation ==> STR, NATIVE :
            STR s|tatic_prefix = "Java;Android;OS[" 
            NATIVE "RESULT = X_s + System_functions.OS() + " #QU "]" #QU ";" .
            
        FUN platform_info|rmation ==> STR, PUBLIC := Platform_info.Lower .
            
        FUN Windows_ver|sion ==> STR : .
        
		FUN Is_int32 ==> BOOL : = 3.ShiftL(31) < 0 .
        
        FUN Is_int64 ==> BOOL : = !Is_int32 .        
            
        FUN TEST|_stage ==> BOOL, NATIVE :
        @   "   RESULT = AL4_system.Is_TEST_stage();" .  
        */
        public static String OS() {
            String s = android.os.Build.VERSION.RELEASE.toString() +
            		   ", SDK " + android.os.Build.VERSION.SDK_INT; 
            	// System.getProperty("os.name");
            return s;
        }
        
        /*
        
		FUNCTION Maximum_recursion|_deep ==> INT, NATIVE :
		@	"	RESULT = AL4_system.Max_recursion_deep;" .
		
		FUN Set_maximum_recursion|_deep(
			INT Desired|_value), NATIVE :
			CASE Desired > 10240 ? INT value|_to_set = 10240
			ELSE value = Desired ;
			NATIVE @
			"	AL4_system.Max_recursion_deep = X_value;"
            //"	int[] old = AL4_system.Stack_functions;"
            //"	AL4_system.Stack_functions = new int[X_value * 2];"
            //"	for (int i = 0; i < AL4_system.SP_fun; i++) {"
            //"		if (i >= AL4_system.Stack_functions.Length) break;"
            //"		if (i >= old.Length) break;"
            //"		AL4_system.Stack_functions[i] = old[i];"
            //"}"
			.
        


        CONST INT :
            MAX_INT|EGER_VALUE = 0x7FFF_FFFF
            MIN_INT|EGER_VALUE = 0x8FFF_FFFF .
            
		FUN Count_param
 			|eters_in_command_line ==> INT, NATIVE :
		@   "RESULT = System_functions.command_line_args.size();" .
		
		FUN Parameter
			|_in_command_line_by_index(INT Index|_of_parameter) ==> STR,
		    NATIVE :
		    CASE Index < 0 || Index >= Count_param ? ==> ;
		    CASE Index == 0 ? RESULT = Application_name ==> ;
		    NATIVE
		@	"RESULT = System_functions.command_line_args.get(X_Index);" .    

        FUNCTION Get_command_line ==> STR, NATIVE :
        @   "    RESULT = System_functions.test_command_line;" 
            "    if (RESULT == null) RESULT = "#QU#QU ";" .
        */
        public static String test_command_line = "";
        public static ArrayList<String> command_line_args 
        	= new ArrayList<String>();

        public static void Obtain_command_line(String[] args) {
        	command_line_args.clear();
        	command_line_args.add("");
            test_command_line = System.getProperty("program.name");
            for (String s : args) {
        		command_line_args.add(s);
                test_command_line += " " + s;
            }
        }

        /*
        
        FUNCTION Change_command_line(STR Val|ue_to_set), NATIVE :
        @   "    if (X_Val == null) X_Val = " #QU#QU ";"
            "    System_functions.test_command_line = X_Val;" .
            
            
        FUN Set_working_dir|ectory(
        STR Path|_directory),
        DEPRECATED('PLATFORM SPECIFIC, not appropiate for ANDROID') : .
            //"    System.setProperty(" #QU "user.dir" #QU ", X_Path);" .

        FUN Get_working_dir|ectory ==> STR, NATIVE :
            //"    RESULT = System.getProperty(" #QU "user.dir" #QU ");"
            //"RESULT = MainActivity.main_activity.getApplicationInfo().dataDir;"
            "RESULT = MainActivity.main_activity.getExternalFilesDir(null)"
            ".toString() + '/';"
            .
            
            
        FUN Get_windows_dir|ectory ==> STR, NATIVE :
           @"    String comspec = System.getenv(" #QU "ComSpec" #QU ");"
            "    if (!comspec.equals(" #QU #QU "))"
            "       for (int j = comspec.length()-1; j >= 0; j--)"
            "           if (comspec.substring(j,j+1) == java.io.File.separator)"
            "              RESULT = comspec.substring(0, j);"
            "    if (RESULT.equals("#QU#QU")) {" 
            "       String path = System.getenv(" #QU "PATH" #QU ");"
            "       int i = path.indexOf(';');"
            "       if (i >= 0) RESULT = path.substring(0, i);"
            "       else RESULT = System.getProperty(" #QU "user.home" #QU ");"
            "    }" .
            
        FUN Get_system_drive ==> STR,
        DEPRECATED('PLATFORM SPECIFIC: Only Windows')
        	:
            RESULT = Get_windows_dir.[0 TO 1] "/"
            CASE RESULT.[1] != ":" ? RESULT = "C:/" ; .
                    
		CONST INT : 
			EXECUTE_REDIRECT_OUT || REDIR_OUT = 1
			EXECUTE_REDIRECT_ERR || REDIR_ERR = 2
			EXECUTE_REDIRECT_IN  || REDIR_IN = 4
			EXECUTE_HIDDEN|_DUMMY || EXEC_HIDDEN = 8
			EXECUTE_RUNAS|_DUMMY || EXECUTE_RUN_AS = 16
			.            
        FUN Execute_program(STR App|lication_path, STR Param|eters,
            INT Redirect|_output_error) ==> STR
            :
            -------- 'It is not allowed to run external apps while testing code'
            << #NL "executing(" Redirect.Str "): " App " " Param #NL #NL
            CASE TEST ?
                 STOP "In TEST mode, can not execute external programs" ;
            RESULT = execute_program( App, Param, Redirect) 
            << #NL "executed ------------------------------------------ " #NL .

        FUN execute_program(STR App|lication_path, STR Param|eters,
                INT Redirect|_output_error) ==> STR, NATIVE :
           @"    try {"
            "        Process p = null;"
            "        ProcessBuilder pb = new ProcessBuilder ("
            "                X_App,"
            "                X_Param"
            "             );"
            "        p = pb.start();"
            "        java.io.BufferedReader bri = null;"
            "        if ((X_Redirect & 1) != 0)"
            "           bri = new java.io.BufferedReader("
            "		    new java.io.InputStreamReader(p.getInputStream()));"
            "	     java.io.BufferedReader bre = null;"
            "        if ((X_Redirect & 2) != 0)"
            "           bre = new java.io.BufferedReader("
            "		    new java.io.InputStreamReader(p.getErrorStream()));"
            "	     String line;"
            "        if ((X_Redirect & 1) != 0) {"
            "	        while ((line = bri.readLine()) != null) {"
            "		     //System.out.println(line);"
            "		     RESULT += line + " #QU "\r\n" #QU ";"
            "	        }"
            "	        bri.close();"
            "        }"
            "        if ((X_Redirect & 2) != 0) {"
            "	        while ((line = bre.readLine()) != null) {"
            "		     //System.out.println(line);"
            "		     RESULT += line + " #QU "\r\n" #QU ";"
            "	        }"
            "	        bre.close();"
            "        }"
            "	     p.waitFor();"
            "	     System.out.println(" #QU "Done: " #QU " + p.exitValue());"
            "    }"
            "	 catch (Exception err) {"
            "	     err.printStackTrace();"
            "        RESULT = " #QU #QU ";"
            "	 }" .

        FUN Start_program_ok(
        STR App|lication_path, STR Param|eters) ==> BOOL
            :
            CASE TEST ? STOP "In TEST mode, can not start external programs" ;
            RESULT = start_program(App, Param, TRUE) .

        FUN Start_program(STR App|lication_path, STR Param|eters) :
            CASE TEST ? STOP "In TEST mode, can not start external programs" ;
            NONE = start_program(App, Param, TRUE) .

        FUN Program_run_as|_same_as_Start_program(
        STR App|lication_path, STR Param|eters)
            :
            CASE TEST ? STOP "In TEST mode, can not start external programs" ;
            NONE = start_program(App, Param, TRUE) .

        FUN Start_program_hidden(
        STR App|lication_path, STR Param|eters)
            :
            CASE TEST ? STOP "In TEST mode, can not start external programs" ;
            NONE = start_program(App, Param, FALSE) .

        FUN start_program(
        STR App|lication_path, STR Param|eters, 
        BOOL Visible|_on_screen) ==> BOOL, NATIVE :
            "    try {"
            "		 ProcessBuilder pb = new ProcessBuilder ("
            "                X_App,"
            "                X_Param"
            "        );"
            //"		 if (!X_Visible) ???"
            "        RESULT = pb.start() != null;"
            "    }"
            "    catch (Exception err) {"
            "    }".

        FUN Ref_count({Object} Obj|ect_inspecting) ==> INT, NATIVE :
            "RESULT = X_Obj.Count;" .

        FUN Stop_if_test(STR T|est_must_be_present) :
            CASE !TEST ? ==> ;
            CASE "test" IN T.Lower ? ==> ;
            
            STOP "In test mode files can not be changed unless these have "
                 "'test' substring in a name or a path".

        FUN Get_environment_var|iable(
            STR Name|_of_variable) ==> STR, NATIVE :
            "    RESULT = System.getenv(X_Name);" 
            "    if (RESULT == null) RESULT = " #QU#QU "; ".
			
        FUNCTION Start_dir ==> STR, NATIVE :
    	"ApplicationInfo aInf = AL4_form.context_activity.getApplicationInfo();"
    	"RESULT = aInf.publicSourceDir;"
    	.

        FUNCTION Application_name ==> STR, NATIVE : @
    	"ApplicationInfo aInf = AL4_form.context_activity.getApplicationInfo();"
    	"int sId = aInf.labelRes;"
    	"if (sId == 0) RESULT = aInf.nonLocalizedLabel.toString();"
    	"else RESULT = AL4_form.context_activity.getString(sId);"
    	.
    	
        FUN Get_recent_files_dir ==> STR : .
            
        FUN Get_temp_dir
            ||Get_temporary_dir|ectory ==> STR, NATIVE : @
        "	RESULT = AL4_form.context_activity.getFilesDir().getAbsolutePath()"
        " 	+ File.separator;" .
        
        CONST INT {special_folders} :
              APPLICATION_DATA = 26
              MY_DOCUMENTS = 5
              DESKTOP_DIR = 0
              STARTUP|_AUTOSTART = 0
              //MY_PICTURES = 39
              //USER_PROFILE = 40 
              .
              
        FUN Get_special_dir|ectory(
        INT Sp|ecial_filder_index ) ==> STR, 
        NATIVE, IF Sp IS CONST, THEN Sp IN {special_folders} : @
        "switch(X_Sp)"
        "{"
        "case 26:"
        "	File f = new java.io.File("
        "		AL4_form.context_activity.getApplicationInfo().dataDir);"
        "	return f.getAbsolutePath() + File.separator;"
        "}" .
        
        FUN Get_application_data_dir|ectory ==> STR :
			RESULT = Get_special_dir(APPLICATION_DATA) .
            
        

--------------- 'environment'
        
        FUNCTION Computer_name ==> STR, NATIVE :
        @   "try {"
            "   InetAddress addr = InetAddress.getLocalHost();"
            "   RESULT = addr.getHostName();"
            "}"
            "catch (Exception E) { }" .    
            
		FUNCTION User_name ==> STR, NATIVE : @
       ''RESULT = System.getProperty("user.name");''
		.
            
            
        FUNCTION Allocate_bytes(
        BYTE Buffer|_bytes[], INT Size|_allocate ), NATIVE :
            "    X_Buffer.Reallocate(X_Size);" .
            
        //FUN Byte|_from_integer(
        //INT Value|_to_get_lower_byte_only) ==> BYTE,
        //    NATIVE : @ "    RESULT = (byte)X_Value;" .
        	
        FUN Copy_bytes|_from_one_array_to_another(
        BYTE Dest|ination_array[*],
        BYTE Source|_array[*])
        	:
        	INT count|_to_copy = Source[].Count
        	CASE count > Dest[].Count ?
        	     count = Dest[].Count ;
        	CASE count <= 0 ? ==> ;
        	do_Copy_bytes(Dest[0 TO *], Source[0 TO *]) .
        FUN do_Copy_bytes(BYTE Dest|ination_array[*], BYTE Source|_array[*]),
        NATIVE: @
        	"	for (int i = 0; i < X_Source.Count(); i++)"
        	"		X_Dest.Set_item(i, X_Source.Get_item(i));" .
        	
        	
--------------- 'sound'

		FUN System_beep : System_tone_beep(500, 500) .
		
		FUN System_tone_beep(
		INT Freq|uency_ignored, INT Dur|ation), NATIVE : @
       "ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);"
       "toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, X_Dur);" .

            
        FUNCTION Sleep|_milliseconds(INT M|illiseconds), NATIVE :
            "    java.lang.Thread.sleep(X_M);" .
            
        FUN Save_DynAStr_to_file( STR S|trings_to_save[], STR Path|_file ),
            NATIVE :
           @"    String nl = System.getProperty(" #QU "line.separator" #QU ");"
            "    try {"
            "        java.io.BufferedWriter bw = new java.io.BufferedWriter("
            "               new java.io.OutputStreamWriter("
            "               new java.io.FileOutputStream(X_Path, false)));"
            "        try {"
            "            for (int i = 0; i < X_S.Count(); i++)"
            "                bw.append(X_S.Get_item(i)).append(nl);"
            "        }"
            "        finally {"
            "            bw.close();"
            "        }"
            "    }"
            "    catch (Exception E_io) {"
            "    }" .
            
        FUN Total_obj_index( 
        {Object} Obj|ect_of_any_class ) ==> INT,
            NATIVE :
           @"    RESULT = X_Obj.Obj.TOTAL_obj_index;" .
           
        FUN Absolute_path|_from_relative_path(
        STR Path|_relative ) ==> STR, 
            NATIVE :
           @"   java.io.File f = new java.io.File(X_Path);"
            "   RESULT = f.getAbsolutePath();" .
            
        FUN Trace_levels ==> INT, NATIVE :
		@	"	RESULT = AL4_system.Get_trace_levels();" .
		
		FUN Trace_fun|ction(
			INT Level|_of_stack_0_is_current_function_Trace_fun) ==> STR,
			NATIVE :
		@	"	RESULT = AL4_system.Get_trace_fun(X_Level);" .
		
		FUN Trace_counter(
			INT Level|_of_stack_0_is_current_function_Trace_fun) ==> INT,
			NATIVE :
		@	"	RESULT = AL4_system.Get_trace_counter(X_Level);" .
		
		FUN Trace_stack(INT Max_levels) ==> STR :
			FOR i IN [0 TO Trace_levels-1] :
			    CASE i >= Max_levels ? ==> ;
			    CASE RESULT != "" ? RESULT = _ #NL ;
			    RESULT = _ Trace_fun(i) #TAB Trace_counter(i).Str ; .
			    
		FUN Real_as_array_of_bytes(
		REAL R|eal_value, BYTE A|rray_bytes|_preallocated_8_items[]), NATIVE : @
		"long lng = Double.doubleToLongBits(X_R);"
		"	for (int i = 0; i < X_A.Count(); i++)"
		"	{"
		"		X_A.Set_item(i, (byte)lng);"
		"		lng = lng >> 8;"     
		"	}" .     
			
		ENUM {play_command} :
	    'PLAY|_FROM_POSITION_PERCENTS',
	    'PAUSE|_PLAYING_AND_CHANGE_POSITION',
	    'RESUME|_PLAYING',
	    'STOP|_PLAYING',
	    'POSITION_INFO|RMATION_GET_POSITION_PLAYING',
	    'LENGTH_INFO|RMATION_MILLISECONDS',
	    'VOLUME|_GET_SET_PERCENTS' .
		

		FUN Play_audiofile(
		STR Full_path|_file,
		{play_command} Command|_to_execute,
		REAL Pos|ition_to_set
		) ==> REAL,
					UNCOOKED
			:		
			.
            
END
*/

    }

