using System;
using System.Collections.Generic;

namespace NcProgramManager.Cnc.Models
{
    /// <summary>Result wrapper for all CNC operations.</summary>
    public sealed class CncResult<T>
    {
        public bool Success { get; }
        public T Value { get; }
        public IReadOnlyList<CncError> Errors { get; }
        public bool WasCancelled { get; }

        private CncResult(bool success, T value, IReadOnlyList<CncError> errors, bool cancelled)
        {
            Success = success;
            Value = value;
            Errors = errors ?? (IReadOnlyList<CncError>)Array.Empty<CncError>();
            WasCancelled = cancelled;
        }

        public static CncResult<T> Ok(T value) =>
            new CncResult<T>(true, value, null, false);

        public static CncResult<T> Fail(IReadOnlyList<CncError> errors) =>
            new CncResult<T>(false, default(T), errors, false);

        public static CncResult<T> Fail(string source, string message) =>
            Fail(new[] { new CncError(0, source, message) });

        public static CncResult<T> Cancelled() =>
            new CncResult<T>(false, default(T), null, true);

        public override string ToString()
        {
            if (WasCancelled) return $"CncResult<{typeof(T).Name}>: Cancelled";
            if (!Success) return $"CncResult<{typeof(T).Name}>: Fail ({Errors.Count} errors)";
            return $"CncResult<{typeof(T).Name}>: Ok";
        }
    }
}
