using System ;
using System.Windows.Forms ;
using System.Diagnostics ;
using System.IO ;
using System.Net ;
using System.Net.Sockets ;
using System.Text ;

namespace FHTE.LTOOLS.GUI
{
	/// <summary>
	/// handles the excecution of the console-application ldir
	/// </summary>
    public sealed class LDir
    {
        // ############################################################################################################
        // FIELDS
        // ############################################################################################################
        string response = "" ;                                  // the response(standard-output) of the ldir-process
        public static MyDebug debugDialog = null ;              // the reference to the DebugDialog
        // ############################################################################################################
        // PROPERTIES
        // ############################################################################################################
        /// <summary>
        /// the property Response returns the response of the ldir-process
        /// </summary>
        public string Response 
        {
            get { return response ; }
        }

        // ############################################################################################################
        // CONSTRUCTORS
        // ############################################################################################################
        /// <summary>
        /// executes a process with commandline-arguments and writes the standard-output in the response variable.
        /// </summary>
        /// <param name="command">the program to start as process</param>
        /// <param name="args">the commandline arguments for the program</param>
        public LDir(string command, string args)
	{

            // 
            // TODO: Add constructor logic here
            //
	    Cursor oldCursor = Cursor.Current;
	    Cursor newCursor = Cursors.WaitCursor;
	    
	    try
	    {   
		Cursor.Current = newCursor;

                SetDebugDialog(LTOOLSnet.debugDialog) ;
                DebugOutput("LDir(): " + command + " " + args) ;
                ProcessStartInfo psi = new ProcessStartInfo() ;
                psi.FileName = command ;
                psi.Arguments = args ;
                psi.CreateNoWindow = true ;                 // don't show a DOS-box
                // psi.WorkingDirectory = Environment.CurrentDirectory ;   // working directory of process
                psi.WorkingDirectory = LTOOLSnet.GUIDirectory ;   // working directory of process
                psi.UseShellExecute = false ;
                psi.RedirectStandardOutput = true ;         // redirect the standardoutput to the Process-instance
                Process proc = Process.Start(psi) ;         // start the process
                StreamReader sr = proc.StandardOutput ;     // StreamReader to read the standard-output of the proc
                response = sr.ReadToEnd() ;                 // write standard-output to the response variable
                sr.Close() ;                                // close the StreamReader

                // cut off the last line of the response, if there are more lines because in the last line
                // there is an info not necessary(Disk space: 33.566 MB of ...). e.g.:
                // ldir
                // drwxr-xr-x    0    0      4096 Tue Apr 08 02:07:59 2003 .
                // drwxr-xr-x    0    0      4096 Tue Apr 08 02:07:59 2003 ..
                // drwxr-xr-x    0    0     49152 Tue Apr 08 02:07:59 2003 lost+found
                // drwxr-xr-x    0    0      4096 Tue Apr 15 00:31:57 2003 test
                // drwxr-xr-x    0    0      4096 Tue Apr 08 02:08:49 2003 joe
                // -rwxrwxrwx    0    0       124 Fri Apr 25 18:01:50 2003 Test.java
                // Disk space: 33.566 MB of 47.031 MB free       
                if ((response.LastIndexOf("\r\n") > 0) && (response.IndexOf("Disk space:") > 0))
                {
                    int lastindex = response.LastIndexOf("\r\n") ;
                    int index = response.LastIndexOf("\r\n", lastindex - 2) ;
                    string test = response.Substring(0, index) ;
                    response = test ;
                }
                proc.Close() ;
                    
                // if there was a "-x" in the argumentsstring, then delete the "zzz.zwz"-file
                string tempfile = "zzz.zwz" ;
                if (args.IndexOf("-x") > 0)
                {
                    if (File.Exists(tempfile))
                    {
                        File.Delete(tempfile) ;
                    }
                }
                /*
                // old version with the zzz.zwz-file
                // ######################################################################
                proc.WaitForExit() ;
                Stream stm = new FileStream ("zzz.zwz", FileMode.Open, FileAccess.Read) ;
                StreamReader sr = new StreamReader(stm) ;
                response = sr.ReadToEnd() ;
                sr.Close() ;
                stm.Close() ;
                */
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "LTOOLS", MessageBoxButtons.OK, MessageBoxIcon.Error) ;
            }
	    Cursor.Current = oldCursor;
        }

        /// <summary>
        /// executes a process with commandline-arguments and writes the standard-output in the response variable.
        /// </summary>
        /// <param name="command"></param>
        /// <param name="args"></param>
        /// <param name="s"></param>
        public LDir(string command, string args, Socket s)
        {
	    Cursor oldCursor = Cursor.Current;
	    Cursor newCursor = Cursors.WaitCursor;
	    try
            {
		Cursor.Current = newCursor;
		
		SetDebugDialog(LTOOLSnet.debugDialog) ;
                DebugOutput("LDir()-remote: " + command + " " + args) ;
                //Sets up variables and a string to write to the server
                Encoding ASCII = Encoding.ASCII;
                string Get = "EXECUTE\n" + command + " " + args + "\n" ; 

                Byte[] ByteGet = ASCII.GetBytes(Get);
                Byte[] RecvBytes = new Byte[LTOOLSnet.BUFSIZE];
                String strRetPage = null;
 
                // Sends the GET text to the host.
                s.Send(ByteGet, ByteGet.Length, SocketFlags.None);
 
                // Receives the page, looping until all bytes are received
                Int32 bytes = s.Receive(RecvBytes, RecvBytes.Length, 0);

                strRetPage = "";
                strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, bytes);
                 
                int bytesToRead, bytesRead = 0 ;
                bytesToRead = Int32.Parse(strRetPage) ;

                response = "" ;
                if (bytesToRead > 0)
                {
                    while (bytesRead < bytesToRead)
                    {
                        bytes = s.Receive(RecvBytes, RecvBytes.Length, SocketFlags.None);
                        bytesRead = bytesRead + bytes ;
                        response = response + ASCII.GetString(RecvBytes, 0, bytes);
                        // DebugOutput("bytesToRead: " + bytesToRead + " - bytesRead: " + bytesRead + " read this loop: " + bytes) ;
                    }
                }
                else
                {
                    response = "" ;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "LTOOLS", MessageBoxButtons.OK, MessageBoxIcon.Error) ;
            }
	    Cursor.Current = oldCursor;
	}

        // ############################################################################################################
        // METHODS
        // ############################################################################################################
        /// <summary>
        /// the GetPartitions() method works with the standardoutput of the "ldir -part" command.
        /// It makes the response string easier to read.
        /// </summary>
        /// <returns>a string with all partitions on the machine (local or remote)</returns>
        public string GetPartitions()
        {   DebugOutput("GetPartitions()");
            // String rawInfo = execOperatingSystemCommand("ldirNT -x -part",true);
            string rawInfo = response ;
            string partInfo = "*** Partition table info from LTOOLS: ***\n";
            string temp, temp1 ;
            string disk = "" ; 

            int i=0,j=0, k=0;
            while (true)
            {
                i = rawInfo.IndexOf("#",i);	                    // Find line starting with '#'
                if (i<0)					    // Bail out, if all lines have been scanned
                {
                    break;
                }
                j = rawInfo.IndexOf("\n",i);			    // Find end of this line
                
                if ((k = rawInfo.Substring(i,j-i).IndexOf("Disk ")) > 0)    // Line containing disk info
                {
		    //              temp = rawInfo.substring(i,j).substring(k+5,k+8); 
		    disk = rawInfo.Substring(i, j-i).Substring(k + 11, 8);	//Get disk name 
                    partInfo = partInfo + 
                        "------------------------------------------------\n" ;
                }
                else if ((k = rawInfo.Substring(i,j-i).IndexOf("Type:")) > 0)	//Line containing partition info
                {
                    temp1= rawInfo.Substring(i,j-i).Substring(1,3);		    //Partition number
                    temp = rawInfo.Substring(i,j-i).Substring(k+5,(k+25) - (k+5));		//Partition type
                    partInfo = partInfo + " " + disk + temp1 + " :   " + temp + "\n" ;
                }
		else if ((k = rawInfo.Substring(i, j-i).IndexOf("RFSTOOL infos")) > 0)	//Line containing RFSTOOL header 
		{
		    partInfo = partInfo + "\n*** Partition table info from RFSTOOL: ***\n";
		}
                i = j; // goto next line
            }  
            return partInfo;
        }

        /// <summary>
        /// the SetDebugDialog() method sets the debugDialog reference to a MyDebug-form
        /// </summary>
        /// <param name="dDialog">a reference to a MyDebug-form</param>
        public void SetDebugDialog(MyDebug dDialog)
        {
            debugDialog = dDialog ;
        }

        /// <summary>
        /// appends a text to the debugDialog
        /// </summary>
        /// <param name="str">the string to append</param>
        void DebugOutput(string str)
        {
            if (debugDialog != null)
            {
                debugDialog.AppendText(str + "\r\n") ;
            }
        }
    }
}
