using System;
using System.Collections.Generic;
using BO.AppServer.Metadata.Enums;
using Quadarax.Foundation.Core.QConsole;
using Quadarax.Foundation.Core.QConsole.Argument;
using Quadarax.Foundation.Core.QConsole.Value;


namespace BO.Console.Commands.Base
{
    internal abstract class AbstractGetCommand : BaseCommand
    {
        #region *** Constants ***

        protected const string CS_ARG_NAME_ID = "id";
        private const string CS_ARG_HINT_ID = "<id>";
        private const string CS_ARG_DESC_ID = "Record identifier (long). Alternative to argument '" + CS_ARG_NAME_NAME + "'.";

        protected const string CS_ARG_NAME_NAME = "name";
        private const string CS_ARG_HINT_NAME = "<name>";
        private const string CS_ARG_DESC_NAME = "Record name or code identifier. Alternative to argument '" + CS_ARG_NAME_ID + "'.";

        protected const string CS_ARG_NAME_DETAILS = "details";
        private const string CS_ARG_HINT_DETAILS = "<show_details>";
        private const string CS_ARG_DESC_DETAILS = "Flag if show more details (related tables).";
        #endregion

        #region *** Properties ***
        protected IdentificationTypeEnum IdentificationType { get; private set; }
        protected string IdentificationValue { get; private set; }

        #endregion

        #region *** Constructors ***
        protected AbstractGetCommand(Engine engine) : base(engine)
        {
        }
        #endregion


        #region *** Protected Overrides ***

        protected override void BeginExecute()
        {
            base.BeginExecute();

            // Parsing input values
            IdentificationType = WasArgumentSpecified(CS_ARG_NAME_ID)
                ? IdentificationTypeEnum.Id : IdentificationTypeEnum.Name;
            IdentificationValue = WasArgumentSpecified(CS_ARG_NAME_ID)
                ? GetArgumentValueOrDefault<int>(CS_ARG_NAME_ID).ToString() : GetArgumentValueOrDefault<string>(CS_ARG_NAME_NAME);

            WriteCaption($"Getting entity by {IdentificationType}={IdentificationValue} ..." );
        }

        protected override void OnValidateArguments()
        {
            base.OnValidateArguments();
            if (!WasArgumentSpecified(CS_ARG_NAME_ID) && !WasArgumentSpecified(CS_ARG_NAME_NAME) 
                || 
                WasArgumentSpecified(CS_ARG_NAME_ID) && WasArgumentSpecified(CS_ARG_NAME_NAME)
                )
                throw new ArgumentException(
                    $"Argument {Engine.Configuration.CharacterNamedArgumentSeparator}{CS_ARG_NAME_ID} or {Engine.Configuration.CharacterNamedArgumentSeparator}{CS_ARG_NAME_NAME} must be specified!");

        }

        protected override IEnumerable<AbstractArgument> OnSetupArguments()
        {
            var args =  new List<AbstractArgument>(base.OnSetupArguments());
            args.Add(new NamedArgument(CS_ARG_NAME_ID, CS_ARG_DESC_ID, CS_ARG_HINT_ID,TypeValuesEnum.Integer,string.Empty,false));
            args.Add(new NamedArgument(CS_ARG_NAME_NAME, CS_ARG_DESC_NAME, CS_ARG_HINT_NAME,TypeValuesEnum.String,string.Empty,false));
            args.Add(new FlagArgument(CS_ARG_NAME_DETAILS, CS_ARG_DESC_DETAILS, CS_ARG_HINT_DETAILS, false));
            return args;
        }


        #endregion


    }
}
