/***********************************************************************
 * 
 *  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.Threading;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Configuration.Install ;

using sscs.communication;
using sscs.constants;
using sscs.common;

namespace sscs.init
{
	public class WinSecretStoreClientService : System.ServiceProcess.ServiceBase
	{
		/// <summary> 
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;		
		private static Communication server;
		private static Thread listeningThread;

		public static string sServiceName = "Novell Identity Store";

		public WinSecretStoreClientService()
		{
			// This call is required by the Windows.Forms Component Designer.
			InitializeComponent();

			// TODO: Add any initialization after the InitComponent call
		}

		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			// 
			// SecretStoreClientService
			// 
			this.CanHandlePowerEvent = true;
			this.ServiceName = "SecretStoreService";

		}
		#endregion

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing ) 
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		static void Main(string[] args)
		{
			string opt = null ;			
			if ( args.Length > 0)
			{
				opt = args [0];
			}

			if (opt != null && opt.ToLower () == "/install")
			{
				stopService();
				uninstallService();
				installService();
				startService();
				return;
			}
			else if (opt != null && opt.ToLower () == "/uninstall")
			{
				stopService();
				uninstallService();
				return;
			}

			if (opt != null && opt.ToLower() == "/standalone")
			{
				MainInternal(args);
			}
			else
			{
				System.ServiceProcess.ServiceBase[] ServicesToRun;
	
				// More than one user Service may run within the same process. To add
				// another service to this process, change the following line to
				// create a second service object. For example,
				//
				//   ServicesToRun = new System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
				//
				ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinSecretStoreClientService() };

				System.ServiceProcess.ServiceBase.Run(ServicesToRun);
			}
		}


		private static void installService()
		{
			TransactedInstaller ti = new TransactedInstaller ();
			ProjectInstaller mi = new ProjectInstaller ();
			ti.Installers.Add (mi);
			String path = String.Format ("/assemblypath={0}",
				System.Reflection.Assembly.GetExecutingAssembly ().Location);
			String[] cmdline = {path};
			InstallContext ctx = new InstallContext ("", cmdline );
			ti.Context = ctx;
			try 
			{
				ti.Install ( new Hashtable ());					
			}
			catch (Exception e)
			{				
				System.Diagnostics.Debug.WriteLine(e.ToString());
			}			
		}

		private static void uninstallService()
		{
            // kill all running versions of CASA manager
            Process[] proc = System.Diagnostics.Process.GetProcessesByName("CASAManager");
            for (int i = 0; i < proc.Length; i++)
            {
                try
                {
                    proc[i].Kill();
                }
                catch { }
            }


			TransactedInstaller ti = new TransactedInstaller ();
			ProjectInstaller mi = new ProjectInstaller ();
			ti.Installers.Add (mi);
			String path = String.Format ("/assemblypath={0}",
				System.Reflection.Assembly.GetExecutingAssembly ().Location);
			String[] cmdline = {path};
			InstallContext ctx = new InstallContext ("", cmdline );
			ti.Context = ctx;
			try 
			{
				ti.Uninstall ( null );
			}
			catch (Exception e)
			{
				System.Diagnostics.Debug.WriteLine(e.ToString());
			}
		}

		private static void stopService()
		{
			ServiceController[] services=ServiceController.GetServices();
			foreach(ServiceController x in services)
			{
				if(x.DisplayName.Equals(sServiceName))
				{
					if (x.Status==System.ServiceProcess.ServiceControllerStatus.Running)
					{
						x.Stop();
					}
				}				
			}
			
		}

		private static void startService()
		{
			ServiceController[] services=ServiceController.GetServices();
			// Iterating each service to check that if a service named
			// 'Novell Identity Store' is found then check that its status whether
			// it is running or stopped. If found running then it will
			// stop that service; else it starts that service
			foreach(ServiceController x in services)
			{
				if(x.DisplayName.Equals(sServiceName))
				{
					CSSSLogger.DbgLog("Checking service: " + x.DisplayName);
					if (x.Status==System.ServiceProcess.ServiceControllerStatus.Stopped)
					{
						x.Start();
					}
				}				
			}		
		}


		/// <summary>
		/// Set things in motion so your service can do its work.
		/// </summary>
		/// 
		protected override void OnStart(string[] args)
		{						        			
			AcquireLock();

			server = CommunicationFactory.CreateCommunicationEndPoint();

			listeningThread = new Thread(new ThreadStart(StartServer));
			listeningThread.Start();
			//listeningThread.Join();									
		}
 
		/// <summary>
		/// Stop this service.
		/// </summary>
		protected override void OnStop()
		{
			listeningThread.Abort();
		}

		/* The thread which listens and spawns threads on every accept
		 * starts its execution from this method.
		 */
		private static void StartServer()
		{
			server.StartCommunicationEndPoint();
		}

		/* This ensures that there is only one instance of
		 * SSCS at any point.
		 */
		private static int AcquireLock()
		{
			return RetCodes.SUCCESS;
		}  
 
		private static void MainInternal(string[] args)
		{
			CSSSLogger.ExecutionTrace(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

			try
			{
				int retVal = AcquireLock();
				if( retVal != RetCodes.SUCCESS )
				{
					CSSSLogger.DbgLog("Acquiring lock failed. Terminating CSSS.");
//					Terminate();
				}
         
//				RegisterAtExit();

				CSSSLogger.DbgLog("Client Side SecretStore Service has started.");

				server = CommunicationFactory.CreateCommunicationEndPoint();

				listeningThread = new Thread(new ThreadStart(StartServer));
				listeningThread.Start();
				listeningThread.Join();
			}
			catch(Exception e)
			{
//				Terminate();
			}        
		}

		/* The thread which listens and spawns threads on every accept
		 * starts its execution from this method.
		 */

	}
}