// 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.Text;
using Microsoft.Extensions.ApiDescription.Tool.Commands;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Tools.Internal;

namespace Microsoft.Extensions.ApiDescription.Tool
{
    internal abstract class ProgramBase
    {
        private readonly IConsole _console;
        private readonly IReporter _reporter;

        public ProgramBase(IConsole console)
        {
            _console = console ?? throw new ArgumentNullException(nameof(console));
            _reporter = new ConsoleReporter(_console, verbose: false, quiet: false);
        }

        protected static IConsole GetConsole()
        {
            var console = PhysicalConsole.Singleton;
            if (console.IsOutputRedirected)
            {
                Console.OutputEncoding = Encoding.UTF8;
            }

            return console;
        }

        protected int Run(string[] args, CommandBase command, bool throwOnUnexpectedArg)
        {
            try
            {
                // AllowArgumentSeparator and continueAfterUnexpectedArg are ignored when !throwOnUnexpectedArg _except_
                // AllowArgumentSeparator=true changes the help text (ignoring throwOnUnexpectedArg).
                var app = new CommandLineApplication(throwOnUnexpectedArg, continueAfterUnexpectedArg: true)
                {
                    AllowArgumentSeparator = !throwOnUnexpectedArg,
                    Error = _console.Error,
                    FullName = Resources.CommandFullName,
                    Name = Resources.CommandFullName,
                    Out = _console.Out,
                };

                command.Configure(app);

                return app.Execute(args);
            }
            catch (Exception ex)
            {
                if (ex is CommandException || ex is CommandParsingException)
                {
                    _reporter.WriteError(ex.Message);
                }
                else
                {
                    _reporter.WriteError(ex.ToString());
                }

                return 1;
            }
        }
    }
}
