using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using McMaster.Extensions.CommandLineUtils;

namespace KattekerCreator
{
    [Command(Name = "KattekerCreator", Description = "Creates Installation and Update packages.")]
    [HelpOption("-?")]
    public abstract class ProgramArguments
    {
        private string _changeLog;
        private string _programFile;
        private string _outputDir;

        [Argument(0, Description = "Path to the program file")]
        [FileExists]
        [Required]
        public string ProgramFile
        {
            get => _programFile;
            set => _programFile = Path.GetFullPath(value);
        }
        
        [Option("-L|--changelog", Description = "Path of the changelog file")]
        [FileExists]
        public string ChangeLog
        {
            get => _changeLog;
            set => _changeLog = Path.GetFullPath(value);
        }

        [Option("-C|--channel", Description = "Channel of releasing")]
        public string Channel { get; set; }

        [Option("-O|--output", Description = "Directory for the output")]
        public string OutputDir
        {
            get => _outputDir;
            set => _outputDir = Path.GetFullPath(value);
        }

        [Option("-P|--publish", Description = "Path for output from the point of view of the application")]
        public string PublishDir { get; set; }

        [Option("-V|--version", Description = "Override version number of the application")]
        public string Version { get; set; }

        [Option("-F|--filter", Description = "Filter parameter. Supports minimatch pattern. (see: https://bit.ly/2EhFoP7)")]
        public string FilterAsString { get; set; }

        [Option("-S|--sign", Description = "Sign setup with certificate")]
        public string CertificatePath { get; set; }

        [Option("-Sp|--signPassword", Description = "Password for certificate, if necessary")]
        public string CertificatePassword { get; set; }

        [Option("-G|--config", Description = "Path to the configuration file. Configured settings in file will override all other settings.")]
        [FileExists]
        protected string ConfigurationPath { get; set; }

        protected abstract int OnExecute(CommandLineApplication app);

        protected IEnumerable<string> Filter => string.IsNullOrWhiteSpace(FilterAsString) ? Enumerable.Empty<string>() : FilterAsString.Split(';');

        public static void OverridePropertyValues(object obj, IDictionary<string, string> dictionary)
        {
            var properties = obj.GetType().GetProperties().Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(OptionAttribute)));
            foreach (var property in properties)
            {
                if (dictionary.TryGetValue(property.Name, out var value))
                {
                    property.SetValue(obj, value);
                }
            }
        }

        public static bool TryReadConfigFile(string configurationPath, out IDictionary<string, string> args)
        {
            if (!string.IsNullOrWhiteSpace(configurationPath) && File.Exists(configurationPath))
            {
                var contents = File.ReadAllText(configurationPath);
                var deserializer = new YamlDotNet.Serialization.DeserializerBuilder().Build();
                args = deserializer.Deserialize<Dictionary<string, string>>(contents);
                return true;
            }

            args = default;
            return false;
        }

    }
}