// 
// Copyright (c) 2013-2016 Carsten Sonne Larsen <cs@innolan.dk>
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Threading;
using Ntp.Common.Process;

namespace Ntp.Common.Log
{
    internal static class LogExtensions
    {
        internal static void ClusterError(this LogBase log, Exception e)
        {
            log.WriteLine(
                "Error in scheduler module. Aborting.",
                Severity.Error);

            log.WriteLine(e);
        }

        internal static void ClusterNodeActive(this LogBase log, IRequest request)
        {
            log.WriteLine(
                $"Cluster node {request} is active.",
                Severity.Notice);
        }

        internal static void ClusterNodeAlive(this LogBase log, IRequest request)
        {
            log.WriteLine(
                $"Cluster node {request} is alive.",
                Severity.Notice);
        }

        internal static void ClusterNodeDead(this LogBase log, IRequest request)
        {
            log.WriteLine(
                $"Cluster node {request} is dead.",
                Severity.Notice);
        }

        internal static void ClusterNodeError(this LogBase log, IRequest request, Exception e)
        {
            log.WriteLine(
                $"Error while contacting cluster node {request}.",
                Severity.Warn);

            log.WriteLine(e);
        }

        internal static void ClusterStart(this LogBase log)
        {
            log.WriteLine(
                "Starting cluster module.",
                Severity.Info);
        }

        internal static void HeartbeatStarted(this LogBase log, int interval)
        {
            log.WriteLine(
                $"Heartbeat started with {interval} minutes interval.",
                Severity.Notice);
        }

        internal static void HeartbeatUptime(this LogBase log, string time)
        {
            log.WriteLine(
                $"Heartbeat: Uptime is {time}.",
                Severity.Notice);
        }

        internal static void JobError(this LogBase log, Job job, Exception e)
        {
            log.WriteLine(
                $"Error while executing {job}.",
                Severity.Error);

            log.WriteLine(e);
        }

        internal static void JobExecutionStatus(this LogBase log, Job job, bool error)
        {
            log.WriteLine(
                error
                    ? $"{job} failed."
                    : $"{job} is done.",
                Severity.Debug);
        }

        internal static void ReceivedSignal(this LogBase log, string signal)
        {
            log.WriteLine(
                $"Received signal {signal}",
                Severity.Debug);
        }

        internal static void SchedulerAbort(this LogBase log, Thread thread)
        {
            log.WriteLine(
                $"Aborting thread {thread.Name}.",
                Severity.Warn);
        }

        internal static void SchedulerBehind(this LogBase log)
        {
            log.WriteLine(
                "Behind schedule. Trying to catch up.",
                Severity.Info);
        }

        internal static void SchedulerError(this LogBase log, string name, Exception e)
        {
            log.WriteLine(
                $"Unexpected error in thread {name}.",
                Severity.Error);

            log.WriteLine(e);
        }

        internal static void SchedulerFinished(this LogBase log)
        {
            log.WriteLine(
                "All threads finished.",
                Severity.Notice);
        }

        internal static void SchedulerJobAdded(this LogBase log, JobDescription description, Job job)
        {
            var type = job.Description.JobType;
            var freq = job.Schedule.Frequency;

            var desc = string.IsNullOrWhiteSpace(job.Description.Name)
                ? string.Empty
                : " " + description.Name;

            var fix = job.Schedule.FixedRun
                ? "fixed "
                : string.Empty;

            log.WriteLine(
                freq != 0
                    ? $"{type} job{desc} added to scheduler with {fix}{freq} minutes run interval."
                    : $"{type} job{desc} added to scheduler for a single run.",
                Severity.Info);
        }

        internal static void SchedulerJobExecuting(this LogBase log, ScheduledJob next)
        {
            log.WriteLine(
                $"{next.Job} started.",
                Severity.Info);
        }

        internal static void SchedulerJobStatus(this LogBase log, ScheduledJob scheduledJob)
        {
            string re = scheduledJob.Job.RunCount == 0 ? string.Empty : "re";

            log.WriteLine(
                $"{scheduledJob.Job} {re}scheduled to run {scheduledJob.Run.ToString("HH:mm:ss")}",
                Severity.Debug);
        }

        internal static void SchedulerStart(this LogBase log, int count)
        {
            log.WriteLine(
                $"Starting scheduler with {count} jobs.",
                Severity.Info);
        }

        internal static void SchedulerWaiting(this LogBase log, int count)
        {
            log.WriteLine(
                $"Waiting for {count} threads to finish.",
                Severity.Notice);
        }

        internal static void ShellCommandError(this LogBase log, string message, string error)
        {
            log.WriteLine(
                $"{message} {error}",
                Severity.Warn);
        }

        internal static void ShellCommandExecuting(this LogBase log, string command, string arguments)
        {
            log.WriteLine(
                $"Executing: {command} {arguments}",
                Severity.Debug);
        }

        internal static void SignalClosing(this LogBase log)
        {
            log.WriteLine(
                "Closing down.",
                Severity.Notice);
        }

        internal static void SignalError(this LogBase log, Exception e)
        {
            log.WriteLine(
                "Unrecoverable error in UnixSignal.WaitAny()",
                Severity.Error);

            log.WriteLine(e);
        }

        internal static void SignalHandlerError(this LogBase log, Exception e)
        {
            log.WriteLine(
                "Unrecoverable error in SignalHandler: {e.Message}",
                Severity.Error);

            log.WriteLine(e);
        }

        internal static void SignalInterProcError(this LogBase log)
        {
            log.WriteLine(
                "Error in inter-process communication.",
                Severity.Warn);
        }

        internal static void SignalRefreshing(this LogBase log)
        {
            log.WriteLine(
                "Refreshing logs.",
                Severity.Notice);
        }

        internal static void SignalReloading(this LogBase log)
        {
            log.WriteLine(
                "Reloading configuration.",
                Severity.Notice);
        }

        internal static void UnexpectedSignal(this LogBase log)
        {
            log.WriteLine(
                "Unexpected inter-process signal.",
                Severity.Warn);
        }

        internal static void UnknownSignal(this LogBase log, string signal)
        {
            log.WriteLine(
                $"Received unknown signal {signal}",
                Severity.Warn);
        }
    }
}