definition module DLState;

// StdEnv
import StdEnv;
import LibraryState;
// Linker
import State;
//from ReadLibrary import StaticLibraryModules,StaticLibrarySymbols,StaticLibraryModule,StaticLibrarySym,StaticLibraries, StaticLibrary;
import ProcessSerialNumber;
// IDE 2.0 import
import PmProject;
import target;

// 0.8.1
//from ioTypes import IOState; // winos
//from ioState import IOState; //macos
//1.3
from deltaDialog import IOState;
//3.1
/*2.0
from deltaDialog import ::IOState;
0.2*/

import StdDynamicVersion;

//
import ClientWindow;

import DynamicID;
import StdDynamicLowLevelInterface;
import typetable;
import MemoryState;
import LibraryInstance;
import type_io_equal_types;
import TypeImplementationTable;
import ToAndFromGraph;

:: *DLServerState
	= {
	// general data
		quit_server						:: !Bool
	,	application_path				:: !String
	,	static_application_as_client	:: !Bool
//	,	targets							:: [Target]
	
	// clients
	,	dl_client_states				:: *[*DLClientState]
	
	// client windows
	,	global_client_window			:: !GlobalClientWindow
	
	// conversions
	,	convert_functions					:: !ConvertFunctions
	
	// NEW TO HANDLE .LIB DEMANDS
	,	dlss_lib_mode					:: !Bool
	,	dlss_lib_command_line			:: !{{#Char}} //String
	};
		
DefaultDLServerState :: !*DLServerState;
AddToDLServerState :: *DLClientState *DLServerState -> *DLServerState; 	
RemoveFromDLServerState :: !ProcessSerialNumber !*DLServerState -> (!Bool,!*DLClientState,!*DLServerState);
//ClientExistsInDLServerState :: !Int !*DLServerState -> !(!Bool,!*DLServerState);	
	
// dl_client_states
acc_dl_client_states :: ([*DLClientState] -> (.x,[*DLClientState])) !*DLServerState -> (.x,!*DLServerState);
app_dl_client_states :: ([*DLClientState] -> [*DLClientState]) !*DLServerState -> !*DLServerState;

selacc_client_state :: !ProcessSerialNumber (*DLClientState -> (.x,*DLClientState)) !*DLServerState -> (.x,!*DLServerState);
//selapp_client_state :: 




selacc_app_linker_state :: !ProcessSerialNumber !(*State -> *(.a,*State)) !*DLServerState -> *(.a,*DLServerState);

MainLibrary	:== 0;

:: *DLClientState
	= { 
	// client identification
		id						:: !ProcessSerialNumber
	,	target					:: !Target
	,	cgpath					:: !String
	,	initial_link			:: !Bool
		
	// project settings
	,	project 				:: !Project
	,	updated					:: !Bool
	,	project_name			:: !String
	
	// application linker state
	,	app_linker_state		:: !*State
	
	,	aux_linker_states		:: *{#*State}
	
	// client window
	,	client_window			:: !ClientWindow
	
	// support for block dynamics (only one
	,	dynamic_ids				:: !*DynamicID

/*
	,	stringtable				:: !StringTable
	,	descriptor_usage_table	:: !DescriptorUsageTable
	,	version					:: !Version
*/	
	,	lib_link				:: !Bool
	
	// Library implementation
	,	cs_main_library_name	:: !String
	,	cs_type_tables			:: !*{#TypeTable}
//	,	cs_memory_state			:: [MemoryState]
	
	,	cs_dynamic_info			:: !*{#DynamicInfo}
	
	,	cs_library_instances		:: !*LibraryInstances	// all info specific to a library instance
	,	cs_main_library_instance_i	:: !Maybe !Int
	
	,	cs_intra_type_equalities	:: !*EqTypesState
	
	,	cs_type_implementation_table	:: *TypeImplementationTable
	
	,	cs_to_and_from_graph	:: !ToAndFromGraphTable	
	
	,	cs_n_fixed_available_types	:: !Maybe !Int
	
	,	do_dump_dynamic			:: !Bool
	
	,	cs_n_lazy_dynamics		:: !Int						// first free dynamic
	
	,	cs_lazy_dynamic_index_to_dynamic_id	:: !*{!Maybe !Int}

	,	cs_share_runtime_system	:: !Bool
	};	
instance DynamicIDs DLClientState;
	
DefaultDLClientState :: !*DLClientState;

// ADDED
instance AddMessage DLClientState;


// ClientWindows
timer_id 	:== 0;
free_id		:== timer_id + 1;

openClientWindow :: !String !ProcessSerialNumber !*DLServerState !(IOState !*DLServerState) -> !(!*DLServerState,!(IOState !*DLServerState));
removeClientWindow :: !*DLClientState !*DLServerState !(IOState *DLServerState) -> (!*DLServerState,!(IOState !*DLServerState));
updateClientWindow :: !*DLServerState !(IOState *DLServerState) -> (!*DLServerState,!(IOState *DLServerState));
HandleRequestResult :: (!Bool,!ProcessSerialNumber,!*DLServerState,(IOState !*DLServerState)) -> (!*DLServerState,IOState !*DLServerState);

// NEW

app_state ::  (!*State -> !*State) !*DLClientState -> !*DLClientState;
acc_state ::  (!*State -> (!.x,!*State)) !*DLClientState -> !(!.x,*DLClientState);

class AppPdState s
where {
	app_pd_state :: !(*PDState -> !*PDState) !*s -> !*s
};

instance AppPdState DLClientState;
instance AppPdState State;

class AccPdState s
where {
	acc_pd_state :: !(*PDState -> (!.x,!*PDState)) !*s -> (!.x,!*s)
};

instance AccPdState State;
instance AccPdState DLClientState;

InitServerState :: !*DLServerState (IOState !*DLServerState) -> (!*DLServerState,(IOState !*DLServerState));


:: ConvertFunctions = {
		graph_to_string :: [Version]
	,	string_to_graph :: [Version]
	};
	
/*
	
:: Version = {
		major	:: !Int
	,	minor	:: !Int
	};
	
toVersion :: !Int -> !Version;

fromVersion :: !Version -> !Int;
*/

GetDynamicLinkerDirectory :: !*DLServerState -> (!String,!*DLServerState);

// Implicit pointers (eager)
eager_read_version :: !Version !*DLClientState !*DLServerState -> (!Bool,!Version,!*DLClientState,!*DLServerState);		
eager_write_version :: !*DLClientState !*DLServerState -> (!Bool,!Version,!*DLClientState,!*DLServerState);	

//toFileNameSubString :: !Version -> !String;
get_type_tables :: !*DLClientState -> *(*{#*TypeTable},*DLClientState);
get_ets :: !*DLClientState -> *(!*EqTypesState,*DLClientState);
get_type_implementation_table :: !*DLClientState -> (!*TypeImplementationTable,!*DLClientState);

instance TypeTableOps DLClientState;
instance DynamicInfoOps DLClientState;

instance Library_Instances DLClientState;

print_type_implementation_table :: !*DLClientState -> !*DLClientState;

/*
instance findTypeUsingTypeName DLClientState;
instance findTypeUsingConstructorName DLClientState;
instance findModuleName DLClientState;
*/

get_from_graph_function_address2 :: (!Maybe !Version) !*DLClientState -> (ToAndFromGraphEntry,ToAndFromGraphEntryIndex,!*DLClientState);

instance symbol_n_to_offset DLClientState;

check_whether_implementation_is_available :: !Int !String !*DLClientState -> (!Bool,!*DLClientState);
check_whether_implementation_is_available2 :: !Int !String !*DLClientState -> (!Bool,!Maybe !(!Int,!Int),!*DLClientState);

findLabel :: !String !Int !*DLClientState -> (!Maybe !(!Int,!Int),!*DLClientState);
isLabelImplemented :: !Int !Int !*DLClientState -> (!Maybe !Int,!*DLClientState);

isTypeImplemented :: !LibraryInstanceTypeReference !*DLClientState -> (!Maybe !(!String,[String]),*DLClientState);
isAnyConstructorOfTypeImplemented :: !LibraryInstanceTypeReference !*DLClientState -> (!Maybe !(!String,[String]),*DLClientState);

get_type_label_names :: !TIO_TypeReference !Int !*DLClientState -> (!String,[String],!*DLClientState);

acc_names_table :: !Int !*DLClientState -> *(.{!NamesTableElement},*DLClientState);	

instance findImplementationType DLClientState;

print_type_table_reference :: !Int !TIO_TypeReference !{#*TypeTable} -> (!String,{#*TypeTable});

get_lazy_dynamic_index_to_dynamic_id :: !*DLClientState -> *(!*{!Maybe !Int},!*DLClientState);
