﻿using ArgsParser.Interfaces;

namespace ArgsParser.ArgumentTypes
{
    /// <summary>
    /// All new ArgumentTypes need to inherit from this.
    /// </summary>
    public abstract class ArgumentTypeBase : IArgumentType
    {
        private string m_Name;
        /// <summary>
        /// The unique name of the argument.
        /// </summary>
        public string ArgumentName
        {
            get
            {
                return m_Name;
            }
        }

        private string m_Command;
        /// <summary>
        /// The command the user would pass in from the command line.
        /// </summary>
        public string ArgumentCommand
        {
            get
            {
                return m_Command;
            }
        }

        internal string m_Error;
        /// <summary>
        /// Contains any validation errors that occurred during the parsing process.
        /// </summary>
        public string Error
        {
            get
            {
                return m_Error;
            }
        }

        private bool m_ArgumentFound;
        /// <summary>
        /// Whether or not the argument was found when processing the args array from the console applications Main method.
        /// </summary>
        public bool ArgumentFound
        {
            get
            {
                return m_ArgumentFound;
            }
        }

        private char m_ValueDelimiter;
        /// <summary>
        /// If First:Chris is the argument then the delimiter is ':'.  If ' ' is specified then the next parameter is used. What ever you
        /// specify here is what the user will have to use. Be careful because some values have special characters in them.  ie the value 
        /// 12/25/2015 might be an issue if you ValueDelimiter is a '/'.
        /// </summary>
        public char ValueDelimiter
        {
            get
            {
                return m_ValueDelimiter;
            }
        }

        public ArgumentTypeBase(string name, string command, char valueDelimiter = ':')
        {
            m_Name = name;
            m_Command = command;
            m_ValueDelimiter = valueDelimiter;
        }

        /// <summary>
        /// ABSTRACT: Find the arg specified in ArgumentCommand and populate Value.
        /// </summary>
        /// <param name="args">The args array from the console apps Main method.</param>
        public abstract void ParseArguments(string[] args);

        /// <summary>
        /// Iterate through args and attempt to find the value relevant for this argument based on what is specified in ArgumentCommand.
        /// </summary>
        /// <param name="args">The args array from the console apps Main method.</param>
        /// <returns>If found, the value.  Otherwise, string.Empty.</returns>
        internal string IdentifyValue(string[] args)
        {
            for (int i = 0; i < args.Length; i++)
            {
                var argument = args[i];
                if (argument.ToLower().StartsWith(ArgumentCommand.ToLower()))
                {
                    m_ArgumentFound = true;
                    if (argument.Contains(ValueDelimiter.ToString()))
                    {
                        return ParseSelfContainedArgument(argument, ValueDelimiter);
                    }
                    else if (ValueDelimiter == ' ')
                    {
                        var nextArgument = i + 1 < args.Length ? args[i + 1] : string.Empty;
                        if (!nextArgument.StartsWith("-"))
                        {
                            return nextArgument;
                        }
                        return string.Empty;
                    }
                }

            }
            return string.Empty;

        }

        /// <summary>
        /// Identify the value part of an argument in the ValueDelimiter isn't a ' '.
        /// </summary>
        /// <param name="argument">The argument to parse.  ie firstName:Chris</param>
        /// <param name="delimiter">The ValueDelimiter used in the argument.  ie ':'</param>
        /// <returns></returns>
        private string ParseSelfContainedArgument(string argument, char delimiter)
        {
            if (string.IsNullOrEmpty(argument) || !argument.Contains(delimiter.ToString())) return string.Empty;
            var parts = argument.Split(delimiter);
            if (parts.Length > 1)
            {
                return parts[1].Trim();
            }

            return string.Empty;

        }

    }
}
