namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter18.Listing18_17
{
    using System;
    using System.Reflection;
    using System.Collections.Generic;
    using Listing18_16;

    public class CommandLineHandler
    {
        // ...
        public static bool TryParse(
            string[] args, object commandLine,
            out string errorMessage)
        {
            bool success = false;
            errorMessage = null;

            Dictionary<string, PropertyInfo> options =
                CommandLineSwitchAliasAttribute.GetSwitches(
                    commandLine);

            foreach(string arg in args)
            {
                PropertyInfo property;
                string option;
                if(arg[0] == '/' || arg[0] == '-')
                {
                    string[] optionParts = arg.Split(
                        new char[] { ':' }, 2);
                    option = optionParts[0].Remove(0, 1).ToLower();

                    if(options.TryGetValue(option, out property))
                    {
                        success = SetOption(
                            commandLine, property,
                            optionParts, ref errorMessage);
                    }
                    else
                    {
                        success = false;
                        errorMessage =
            $"Opcja '{ option }' nie jest obsługiwana.";
                    }
                }
            }
            return success;
        }

        private static bool SetOption(
            object commandLine, PropertyInfo property,
            string[] optionParts, ref string errorMessage)
        {
            bool success;

            if(property.PropertyType == typeof(bool))
            {
                // Ostatni parametr służy do obsługi indeksu.
                property.SetValue(
                    commandLine, true, null);
                success = true;
            }
            else
            {

                if((optionParts.Length < 2)
                    || optionParts[1] == ""
                    || optionParts[1] == ":")
                {
                    // Nie podano wartości danej opcji.
                    success = false;
                    errorMessage =
                      $"Należy podać wartość opcji { property.Name }.";
                }
                else if(
                    property.PropertyType == typeof(string))
                {
                    property.SetValue(
                        commandLine, optionParts[1], null);
                    success = true;
                }
                else if(property.PropertyType.GetTypeInfo().IsEnum)
                {
                    success = TryParseEnumSwitch(
                        commandLine, optionParts,
                        property, ref errorMessage);
                }
                else
                {
                    success = false;
                    errorMessage = string.Format(
          $@"Właściwość typu '{ property.PropertyType.ToString() }' nie jest dostępna w typie {
            commandLine.GetType().ToString() }.");
                }
            }
            return success;
        }

        private static bool TryParseEnumSwitch(object commandLine, string[] optionParts, PropertyInfo property, ref string errorMessage)
        {
            throw new NotImplementedException();
        }
    }
}
