using System.Text.Json;
using Quadarax.Foundation.Core.Json;
using Quadarax.Foundation.Core.QConsole;
using Quadarax.Foundation.Core.QConsole.Argument;
using Quadarax.Foundation.Core.QConsole.Attributes;
using Quadarax.Foundation.Core.QConsole.Value;
using Quadarax.Foundation.Core.Value;

namespace Quadarax.Foundation.Core.QMonitor.Console.Commands
{
    [CommandDefinition]
    internal class ScanCommand : BaseCommand
    {

        #region *** Constants ***

        private const string CS_CMD_SCAN_NAME = "scan";
        private const string CS_CMD_SCAN_DESC = "Scans for general metadata informations.";


        protected const string CS_ARG_NAME_DATA = "data";
        private const string CS_ARG_HINT_DATA = "<is_data_included>";
        private const string CS_ARG_DESC_DATA = "Flag if set shows receiving data entry.";

        protected const string CS_ARG_NAME_GENFILE = "genfile";
        private const string CS_ARG_HINT_GENFILE = "<general_file>";
        private const string CS_ARG_DESC_GENFILE = "Saves received general metadata to json file.";
        #endregion

        
        #region *** Properties ***
        public override string Name => CS_CMD_SCAN_NAME;
        public override string Description => CS_CMD_SCAN_DESC;

        private bool IsDataDump { get; set; }
        private string GeneralFile { get; set; }
        #endregion

        #region *** Private fields ***
        private IDictionary<string, MonItemGeneral> _cachedGenerals = new Dictionary<string, MonItemGeneral>();
        #endregion

        #region *** Constructor ***
        public ScanCommand(Engine engine) : base(engine)
        {
        }
        #endregion  

        #region *** Execute ***
        protected override Result OnExecute()
        {
            var waitToData = TimeSpan.FromSeconds(10);
            WriteInfo($"Waiting for collecting general metadata {waitToData.TotalSeconds} seconds...");
            Task.Delay(waitToData).Wait();
            WriteInfo($"Collected {_cachedGenerals.Count} items above.");
            if (!string.IsNullOrEmpty(GeneralFile))
            {
                var list = _cachedGenerals.Values.OrderBy(x=>x.Name).ToArray();
                var binder = new Binder(FileSystem, true, true, 5);
                binder.Save(GeneralFile, list);
                WriteInfo($"Collected general metadata saved to '{GeneralFile}'");
            }
            return new Result();
        }
        #endregion

        #region *** Private Operations ***

        protected override void OnInitialize()
        {
            base.OnInitialize();
            IsDataDump = GetArgumentValueOrDefault<bool>(CS_ARG_NAME_DATA);
            GeneralFile = GetArgumentValueOrDefault<string>(CS_ARG_NAME_GENFILE);
        }
        protected override IEnumerable<AbstractArgument> OnSetupArguments()
        {
            var result = new List<AbstractArgument>(base.OnSetupArguments())
            {
                new NamedArgument(CS_ARG_NAME_GENFILE, CS_ARG_HINT_GENFILE, CS_ARG_DESC_GENFILE, TypeValuesEnum.String, string.Empty, false),
                new FlagArgument(CS_ARG_NAME_DATA, CS_ARG_HINT_DATA, CS_ARG_DESC_DATA, false)
            };
            return result;
        } 
        protected override void OnGeneralReceived(MonGeneral general)
        {
            foreach (var item in general.Items)
            {
                if(!_cachedGenerals.ContainsKey($"{general.InstanceIdentifier}_{item.Name}"))
                {
                    _cachedGenerals.Add($"{general.InstanceIdentifier}_{item.Name}", item);
                    WriteInfo("* [" + general.InstanceIdentifier + "] " + item.Name);
                }
            }
        }

        protected override void OnDataReceived(MonData[] data)
        {
            if (IsDataDump)
            {
                foreach (var item in data)
                {
                    WriteInfo($"# [{item.InstanceIdentifier}] {item.Name}");
                }
            }
        }

        #endregion

    }
}
