/***********************************************************************
 * 
 *  Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library 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
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 ***********************************************************************/

using System;
using System.Text;
using System.Diagnostics;
using sscs.common;
using sscs.constants;
using System.IO;    
using System.Threading;

namespace sscs.common
{
    /*
     * This ia a common logging facility for windows and Linux.
     * This also is the common place to log all server logs and debug logs. 
     */

    class CSSSLogger
    {
        //private static CSSSLogger csssLog = null;
        //private static string WINID = "Microsoft"; 
        private static string engineLog = null;
#if DEBUG 
        private static string LINUXID = "Unix"; 
        private static string debugLog = null;
        private static Stream debugStream= null;
#endif
        private static StreamWriter  serverTrace= null;
        private static Mutex dbgmutex = new Mutex(); 
       
        static CSSSLogger()
        {
#if DEBUG
            if (Environment.OSVersion.ToString().StartsWith(LINUXID))
            {
                engineLog = ConstStrings.SSCS_LINUX_ENGINELOG;
                debugLog  = ConstStrings.SSCS_LINUX_DEBUGLOG;
            }
            else
            {
                engineLog = ConstStrings.SSCS_WIN_ENGINELOG;
                debugLog  = ConstStrings.SSCS_WIN_DEBUGLOG;
            }

             /* There is no set up for Server Trace
              * open and close would be done when needed.
              */

             // Set up for Debug

             if( File.Exists( debugLog ) )
             {
                 File.Delete( debugLog );
             }

             debugStream = File.Create(debugLog);

             Debug.Listeners.Add(new TextWriterTraceListener(debugStream));
             Debug.AutoFlush = true;
             Debug.Indent();
             Debug.WriteLine("Debug Log created");
#endif
          }

        public static void log(bool criticality, String message)
        {
            if (criticality) // Status message
                WritetoServerLog(message);
            else    
                DbgLog(message);
        }

        public static void log(bool criticality, System.Exception e)
        {
            if (criticality) // Status message
                WritetoServerLog(e.ToString());
            else    
                DbgLog(e.ToString());
          
        }

        public static void ExecutionTrace(Object obj)
        {
#if DEBUG
            StringBuilder message = null;
            StackTrace st = null;
            try
            {
                message = new StringBuilder();
                st = new StackTrace(true);
            }
            catch( OutOfMemoryException e )
            {
                ExpLog(e.ToString());
                throw e;
            }
            Type type     = obj.GetType();
            StackFrame sf = st.GetFrame(1);
            message.Append(" ThreadID: ");
            message.Append(Thread.CurrentThread.GetHashCode().ToString());
            message.Append(" Executing Path: ");
            message.Append(type.ToString());
            message.Append(":");
			if (sf != null)
				message.Append(sf.GetMethod().ToString());
			else
				message.Append("Method unknown");

            log( ConstStrings.DEBUG,message.ToString() );
#endif
        }
        
        public static void ExecutionTrace(Type type)
        {
#if DEBUG
            StringBuilder message = null;
            StackTrace st = null;
            try
            {
                message = new StringBuilder();
                st = new StackTrace(true);
            }
            catch( OutOfMemoryException e )
            {
                ExpLog(e.ToString());
                throw e;
            }
            StackFrame sf = st.GetFrame(1);
            message.Append(" ThreadID: ");
            message.Append(Thread.CurrentThread.GetHashCode().ToString());
            message.Append(" Executing Path: ");
            message.Append(type.ToString());
            message.Append(":");
			if (sf != null)
				message.Append(sf.GetMethod().ToString());
			else
				message.Append("Method Unknown");
            log( ConstStrings.DEBUG,message.ToString() );
#endif
        }


        public static string GetExecutionPath(Object obj)
        {
            StringBuilder message = null;
            StackTrace st = null;
            try
            {
                message = new StringBuilder();
                st = new StackTrace(true);
            }
            catch( OutOfMemoryException e )
            {
                ExpLog(e.ToString());
                throw e;
            }
            Type type     = obj.GetType();
            StackFrame sf = st.GetFrame(1);
            message.Append(" ThreadID: ");
            message.Append(Thread.CurrentThread.GetHashCode().ToString());
            message.Append(" Executing Path: ");
            message.Append(type.ToString());
            message.Append("::");
			if (sf != null)
				message.Append(sf.GetMethod().ToString());
			else
				message.Append("Method unknown");

			return message.ToString();
        }  

      
        public static void logbreak()
        {
            dbgmutex.WaitOne();
            Debug.WriteLine("  ") ;
            Debug.WriteLine("----------------------------------------------------") ;
            Debug.WriteLine("  ") ;
            dbgmutex.ReleaseMutex();
          
          }

      // The log format is Time stamp : Machine name: Product name: Logging information
       private static void WritetoServerLog( string message )
       {
            serverTrace = File.AppendText(engineLog);
            serverTrace.Write("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
            serverTrace.Write("CSSS");
            serverTrace.Write(message);
            serverTrace.Flush();
            serverTrace.Close();
       }


       // The log format is Time stamp :Component name: Error description 
        public static void DbgLog(string message)
        {
            dbgmutex.WaitOne();

            Debug.Write(DateTime.Now.ToLongTimeString());
            Debug.Write(" " + DateTime.Now.ToLongDateString());
            Debug.Write(":");
            Debug.WriteLine(message);
//            Debug.WriteLine("  ") ;

            dbgmutex.ReleaseMutex();
        }    
       
        public static void ExpLog(string message)
        {
            dbgmutex.WaitOne();

            Debug.Write(DateTime.Now.ToLongTimeString());
            Debug.Write(" " + DateTime.Now.ToLongDateString());
            Debug.Write(": Exception encountered - ");
            Debug.WriteLine(message);
            Debug.WriteLine("  ") ;
            StackTrace st = new StackTrace();
            Debug.WriteLine(st.ToString());

            dbgmutex.ReleaseMutex();
        }
    }   
}