// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;

using Microsoft.Build.BackEnd;

#nullable disable

namespace Microsoft.Build.Shared
{
    /// <summary>
    /// A result of executing a target or task.
    /// </summary>
    internal class OutOfProcTaskHostTaskResult
    {
        /// <summary>
        /// Constructor 
        /// </summary>
        internal OutOfProcTaskHostTaskResult(TaskCompleteType result)
            : this(result, null /* no final parameters */, null /* no exception */, null /* no exception message */, null /* and no args to go with it */)
        {
            // do nothing else
        }

        /// <summary>
        /// Constructor
        /// </summary>
        internal OutOfProcTaskHostTaskResult(TaskCompleteType result, IDictionary<string, Object> finalParams)
            : this(result, finalParams, null /* no exception */, null /* no exception message */, null /* and no args to go with it */)
        {
            // do nothing else
        }

        /// <summary>
        /// Constructor
        /// </summary>
        internal OutOfProcTaskHostTaskResult(TaskCompleteType result, Exception taskException)
            : this(result, taskException, null /* no exception message */, null /* and no args to go with it */)
        {
            // do nothing else
        }

        /// <summary>
        /// Constructor
        /// </summary>
        internal OutOfProcTaskHostTaskResult(TaskCompleteType result, Exception taskException, string exceptionMessage, string[] exceptionMessageArgs)
            : this(result, null /* no final parameters */, taskException, exceptionMessage, exceptionMessageArgs)
        {
            // do nothing else
        }

        /// <summary>
        /// Constructor
        /// </summary>
        internal OutOfProcTaskHostTaskResult(TaskCompleteType result, IDictionary<string, Object> finalParams, Exception taskException, string exceptionMessage, string[] exceptionMessageArgs)
        {
            // If we're returning a crashing result, we should always also be returning the exception that caused the crash, although 
            // we may not always be returning an accompanying message. 
            if (result == TaskCompleteType.CrashedDuringInitialization ||
                result == TaskCompleteType.CrashedDuringExecution ||
                result == TaskCompleteType.CrashedAfterExecution)
            {
                ErrorUtilities.VerifyThrowInternalNull(taskException, nameof(taskException));
            }

            if (exceptionMessage != null)
            {
                ErrorUtilities.VerifyThrow(
                        result == TaskCompleteType.CrashedDuringInitialization ||
                        result == TaskCompleteType.CrashedDuringExecution ||
                        result == TaskCompleteType.CrashedAfterExecution,
                        "If we have an exception message, the result type should be 'crashed' of some variety.");
            }

            if (exceptionMessageArgs?.Length > 0)
            {
                ErrorUtilities.VerifyThrow(exceptionMessage != null, "If we have message args, we need a message.");
            }

            Result = result;
            FinalParameterValues = finalParams;
            TaskException = taskException;
            ExceptionMessage = exceptionMessage;
            ExceptionMessageArgs = exceptionMessageArgs;
        }

        /// <summary>
        /// The overall result of the task execution. 
        /// </summary>
        public TaskCompleteType Result
        {
            get;
            private set;
        }

        /// <summary>
        /// Dictionary of the final values of the task parameters
        /// </summary>
        public IDictionary<string, Object> FinalParameterValues
        {
            get;
            private set;
        }

        /// <summary>
        /// The exception thrown by the task during initialization or execution, 
        /// if any. 
        /// </summary>
        public Exception TaskException
        {
            get;
            private set;
        }

        /// <summary>
        /// The name of the resource representing the message to be logged along with the 
        /// above exception. 
        /// </summary>
        public string ExceptionMessage
        {
            get;
            private set;
        }

        /// <summary>
        /// The arguments to be used when formatting ExceptionMessage
        /// </summary>
        public string[] ExceptionMessageArgs
        {
            get;
            private set;
        }
    }
}
