<%@ Import Namespace="System.Web.Caching" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>

<script language="c#" runat="server">
/// --------------------------------------------------------------------------------
/// Sample web page to generate and update TreeGrid data, using TreeGrid.dll
/// This page can be used as data source for examples, use Examples/Main/Examples.html?src=../AspNet/AjaxDLLServerPage.aspx
/// TreeGrid.dll must be placed in the ../../Server/ directory, or the path must be changed in Init() function
/// Uses data from ../Data/ directory, or the path must be changed in Init() function
/// Shows server paging features
/// --------------------------------------------------------------------------------
void Page_Init(object sender, System.EventArgs e){
Init();
}
// ----------------------------------------------------------------------------------------------------
void Page_Load(object sender, System.EventArgs e) {
try {
   string F = Request.Params["Function"];
   if(F=="LoadBody") Response.Write(FuncLoadBody(Request.Params["File"], Request.Params["Def"], Request.Params["Data"], Request.Params["Bonus"])); 
   else if(F=="LoadPage") Response.Write(FuncLoadPage(Request.Params["File"], Request.Params["Def"], Request.Params["Data"], Request.Params["Bonus"]));
   else if(F=="Save") Response.Write(FuncSave(Request.Params["File"], Request.Params["Def"], Request.Params["Data"], Request.Params["Bonus"]));
   else Response.Write(Error(-3, "Wrong function requested ["+F+"]"));
   }
catch(Exception ex){
   Response.Write(Error(-3, ex.Message));
   }
}
// ----------------------------------------------------------------------------------------------------
   
      // ###############################################################################################
      // Next processing code is the same as in SrcPage.aspx
      // ###############################################################################################
      
      // Caching - in memory data stay 10 minutes from last access and after that time are saved to tmp file
      // After 12 hours from last access is tmp file deleted
		
      // ----------------------------------------------------------------------------------------------------
      // Inicialization and TreeGrid.dll loading
      void Init() {
      Path = System.IO.Path.GetDirectoryName(Context.Request.PhysicalPath) + "\\";
      Loaded = LoadLibrary(Path + "..\\..\\Server\\TreeGrid.dll")!=IntPtr.Zero; // Load TreeGrid.dll from the same directory as this asmx file
      Path += "..\\ServerDLL\\";
		}
      // ----------------------------------------------------------------------------------------------------
      string Path; // Path to data directory
      bool Loaded; // If DLL successfuly loaded
		// ----------------------------------------------------------------------------------------------------
      // TreeGrid.dll import
      [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
      static extern IntPtr LoadLibrary(string lpFileName);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern int CreateGrid(string Data, string Layout, string Defaults, string Text, string Bonus, string Bonus2);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern int UpdateGrid(int Index, string Bonus);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern int FindGrid(string Cfg);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern int DeleteGrid(int Index);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern void Clear();
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern string GetBody(int Index, string Cfg);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern string GetPage(int Index, string Cfg);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern int Save(int Index, string Input);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern int SaveToFile(int Index, string FileName, int Type);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern string GetData(int Index);
      [DllImport("TreeGrid.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
      public static extern string LastError();
      // ----------------------------------------------------------------------------------------------------
		const string CacheError = "Error: Page validity in cache has expired\nProbably due server side component updates\nPlease reload grid";
		// ----------------------------------------------------------------------------------------------------
		// Returns Xml with given error message
		private string Error(int num, string mess){
      string Err = LastError();
      if(Err!=null && Err!="") mess = mess+"&#x0A;&#x0A;"+Err.Replace("&","&amp;").Replace("<","&lt;").Replace("\"","&quot;");
		return "<Grid><IO Result='"+num+"' Message=\""+mess+"\"/></Grid>";
		}
		// ----------------------------------------------------------------------------------------------------
		// Logs information to Log.txt
		private void Log(string S){ Log(S,true); }
		private void Log(string S, bool cr){
      try {
         System.IO.StreamWriter F = null;
         try { F = System.IO.File.AppendText(Path + "Log.txt"); }
         catch { }
         if (F == null) F = System.IO.File.AppendText(Path + "ErrLog.txt");
         if (cr) F.Write("\r\n" + DateTime.Now.ToUniversalTime().AddHours(1).ToString("yy/MM/dd HH:mm:ss") + "\t" + S);
         else F.Write(S);
         F.Close();
         }
      catch { }
		}
		// ----------------------------------------------------------------------------------------------------
		// Deletes old tmp files
		private void DeleteOld(){
      try {
		   string[]Files = System.IO.Directory.GetFiles(Path+"tmp","*.xml");
		   DateTime T = DateTime.Now - new TimeSpan(12,0,0);
		   foreach(string F in Files){
   		   try {
   				if(System.IO.File.GetLastAccessTime(F) < T){ 
					   Log("\t\tRemoveFile \t"+F+"\t");
					   System.IO.File.Delete(F);
					   Log("\tRemoveFileOK \t");
					   }
			      }
		      catch (Exception E) {
  				   Log("\t\tRemoveFileError\t"+F+"\t"+E.Message);
			      }	
		      }
         }
      catch { }
		}
		// ----------------------------------------------------------------------------------------------------
		// Returns Grids index for given file
      // Add = 0 - return -1 if not found
      // Add = 1 - add if not found
      // Add = 2 - always add
		private int GetIndex(string File, string Def, string Bonus, int Add){
		if(File=="") return -1;
		string ID = Context.Request.ServerVariables["REMOTE_HOST"]+File;
      //string ID = "ID"+(new Random()).Next().ToString();
		object Index = Context.Cache[ID];
		if(Index==null) {
         if(System.IO.File.Exists(Path+"tmp\\"+ID)){
            Log("\tLoadGrid",false);
            Index = CreateGrid(Path+"tmp\\"+ID,Path+Def,Path+"..\\..\\Grid\\Defaults.xml",Path+"..\\..\\Grid\\Text.xml",Bonus,null);
            }
         else {
				DeleteOld();
            Log("\tCreateGrid",false);
            if(Add==0) return -1;
            Index = CreateGrid(Path + File, Path + Def, Path + "..\\..\\Grid\\Defaults.xml", Path + "..\\..\\Grid\\Text.xml", Bonus, null);
            }
         if ((int)Index < 0) return (int)Index;
   	   Context.Cache.Add(ID,Index,null,DateTime.MaxValue,new TimeSpan(0,10,0),CacheItemPriority.NotRemovable,new CacheItemRemovedCallback(OnCacheItemRemoved));
			}
		else if(Bonus!="" && Bonus!=null){
         Log("\tUpdateGrid", false);
			UpdateGrid((int)Index,Bonus);
			}
      return (int)Index;
		}
		// ----------------------------------------------------------------------------------------------------
		// Called to delete grid when its index is removed from cache
		private void OnCacheItemRemoved(string key, object value, CacheItemRemovedReason reason){
		try {
			Log("\t\tRemove\t"+key);
			SaveToFile((int)value,Path+"tmp\\"+key,0);
			DeleteGrid((int)value);
			Log("\tRemoveOK",false);
			}
		catch { Log("\tRemoveError",false); }
		}
		// ----------------------------------------------------------------------------------------------------
		// Returns grid data, for Paging==3 returns only empty pages with information about their content
		// Data contains XML with grid settings - sorting and filters
		private string FuncLoadBody(string File, string Def, string Data, string Bonus) {
      if(!Loaded) return Error(-5, "TreeGrid.dll not found");
		int pg = Bonus!=null ? Bonus.IndexOf("Paging='") : -1;
		if(pg>=0) pg = System.Int32.Parse(Bonus.Substring(pg+8,1));
		string pag;
		if(pg==0) pag="None";
		else if(pg==2) pag="Client";
		else if(pg==3) pag="Server";
		else pag="PagingError";
		Log(Context.Request.ServerVariables["REMOTE_HOST"] + "\tLoadBody\t"+File+"\t"+pag);
      Log("\t" + Data, false);
      int Index = GetIndex(File,Def,Bonus,1);
      if (Index < 0) return Error(-1, "Server DLL Error: TreeGrid data not found or server has not permission to read them&#x0A;Data are located at /Examples/ServerDLL/");
      string Ret = GetBody(Index,Data);
		if(Ret==null) return Error(-4,"Server DLL Error: TreeGrid data cannot be loaded");
		Log("\tBodyOK",false);
		return Ret;
      }
		// ----------------------------------------------------------------------------------------------------
		// Returns children of one page or one row
		// Data contains XML with page index or row id and grid settings - sorting and filters
		private string FuncLoadPage(string File, string Def, string Data, string Bonus) {
      if(!Loaded) return Error(-5, "TreeGrid.dll not found");
      Log(Context.Request.ServerVariables["REMOTE_HOST"] + "\tLoadPage\t"+File+"\t      ");
      Log("\t" + Data + "\t      ", false);
		int Index = GetIndex(File,Def,Bonus,0);
		if(Index<0){ 
         Log("\tCacheError",false);
			return Error(-2,CacheError);// Platnost cache vyprsela
			}
      string Ret = GetPage(Index,Data);
		//Log(Ret);
      if(Ret==null){ 
         Log("\tCfgError",false);
         return Error(-3, "Server DLL Error: Configuration changed, you need to reload grid!");
			}
		Log("\tPageOK",false);
      return Ret;
		}
		// ----------------------------------------------------------------------------------------------------
		// Saves changed data to XML file
		// Data contains XML with changed rows
		private string FuncSave(string File, string Def, string Data, string Bonus) {
      if(!Loaded) return Error(-5, "TreeGrid.dll not found");
      Log(Context.Request.ServerVariables["REMOTE_HOST"] + "\tSave     \t" + File + "\t      ");
      Log("\t"+Data+"\t      ", false);
		int Index = GetIndex(File,Def,Bonus,0);
		if(Index<0){ 
         Log("\tCacheError",false);
			return Error(-2,CacheError); // Platnost cache vyprsela
			}
      int Ret = Save(Index,Data);
      if(Ret>0){ 
         Log("\tSaveWarning",false);
         return Error(0, "Server DLL Warning: Not all data were successfully saved !");
			}
		if(Ret<0){ 
         Log("\tSaveError",false);
         return Error(Ret, "Server DLL Error: Changes were not saved");
			}
		Log("\tSaveOK",false);
      return Error(0,"");
		}
		// ----------------------------------------------------------------------------------------------------
       
      // ###############################################################################################
      // End of processing code
      // ###############################################################################################
</script>


