﻿/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if (!NETCOREAPP)
namespace Apache.Ignite.Core.Tests
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.ServiceProcess;
    using Apache.Ignite.Core.Cluster;
    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
    using Apache.Ignite.Core.Log;
    using Apache.Ignite.Core.Tests.Process;
    using NUnit.Framework;

    /// <summary>
    /// Tests windows service deployment and lifecycle.
    /// <para />
    /// NOTE: This fixture requires administrative privileges.
    /// </summary>
    public class WindowsServiceTest
    {
        /// <summary>
        /// Test fixture set up.
        /// </summary>
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            StopServiceAndUninstall();
        }

        /// <summary>
        /// Test fixture tear down.
        /// </summary>
        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            StopServiceAndUninstall();
        }

        /// <summary>
        /// Tests that service stops when Ignition stops.
        /// </summary>
        [Test]
        public void TestStopFromJava()
        {
            var startTime = DateTime.Now.AddSeconds(-1);

            var exePath = typeof(IgniteRunner).Assembly.Location;
            var springPath = Path.GetFullPath(@"config\compute\compute-grid1.xml");

            JvmDll.Load(null, new NoopLogger());
            var jvmDll = System.Diagnostics.Process.GetCurrentProcess().Modules
                .OfType<ProcessModule>()
                .Single(x => JvmDll.FileJvmDll.Equals(x.ModuleName, StringComparison.OrdinalIgnoreCase));

            IgniteProcess.Start(exePath, string.Empty, args: new[]
            {
                "/install",
                "ForceTestClasspath=true",
                "-springConfigUrl=" + springPath,
                "-jvmDll=" + jvmDll.FileName
            }).WaitForExit();

            var service = GetIgniteService();
            Assert.IsNotNull(service);

            service.Start();  // see IGNITE_HOME\work\log for service instance logs
            WaitForStatus(service, startTime, ServiceControllerStatus.Running);

            using (var ignite = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration())
            {
                SpringConfigUrl = springPath
            }))
            {
                Assert.IsTrue(ignite.WaitTopology(2), "Failed to join with service node");

                // Stop remote node via Java task
                // Doing so will fail the task execution
                Assert.Throws<ClusterGroupEmptyException>(() =>
                    ignite.GetCluster().ForRemotes().GetCompute().ExecuteJavaTask<object>(
                        "org.apache.ignite.platform.PlatformStopIgniteTask", ignite.Name));

                Assert.IsTrue(ignite.WaitTopology(1), "Failed to stop remote node");

                // Check that service has stopped.
                WaitForStatus(service, startTime, ServiceControllerStatus.Stopped);
            }
        }

        /// <summary>
        /// Waits for service status.
        /// </summary>
        private static void WaitForStatus(ServiceController service, DateTime startTime,
            ServiceControllerStatus status)
        {
            try
            {
                service.WaitForStatus(status, TimeSpan.FromSeconds(30));
            }
            catch (Exception ex)
            {
                // Check Windows log for more details.
                var log = EventLog.GetEventLogs().Single(x => x.Log == "Application");
                var entries = log.Entries;
                var recentEntries = Enumerable.Range(0, entries.Count)
                    .Select(x => entries[x])
                    .Where(x => x.TimeGenerated >= startTime)
                    .Select(x => x.Message);
                var msg = string.Join("\n===\n", recentEntries);

                throw new Exception("Failed to start service. Event entries:\n" + msg, ex);
            }
        }

        /// <summary>
        /// Stops the service and uninstalls it.
        /// </summary>
        private static void StopServiceAndUninstall()
        {
            var controller = GetIgniteService();

            if (controller != null)
            {
                if (controller.CanStop)
                    controller.Stop();

                controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));

                var exePath = typeof(IgniteRunner).Assembly.Location;
                IgniteProcess.Start(exePath, string.Empty, args: new[] {"/uninstall"}).WaitForExit();
            }
        }

        /// <summary>
        /// Gets the ignite service.
        /// </summary>
        private static ServiceController GetIgniteService()
        {
            return ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.StartsWith("Apache Ignite.NET"));
        }

        private class NoopLogger : ILogger
        {
            public void Log(LogLevel level, string message, object[] args, IFormatProvider formatProvider, string category,
                string nativeErrorInfo, Exception ex)
            {
                // No-op.
            }

            public bool IsEnabled(LogLevel level)
            {
                return false;
            }
        }
    }
}
#endif
