/*
 * Argument.cs --
 *
 * Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 */

using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using Eagle._Attributes;
using Eagle._Components.Private;
using Eagle._Constants;
using Eagle._Containers.Public;
using Eagle._Interfaces.Private;
using Eagle._Interfaces.Public;

namespace Eagle._Components.Public
{
#if SERIALIZATION
    [Serializable()]
#endif
    [ObjectId("3db192d7-76fa-485f-949c-a75bd929e66a")]
    public sealed class Argument :
            IArgument, IScriptLocation, IToString, IString
    {
        #region Private Constants
        public static readonly ArgumentFlags NoFlags = ArgumentFlags.None;
        public static readonly string NoName = String.Empty;
        public static readonly string NoValue = String.Empty;
        public static readonly string NoString = null;
        public static readonly string NoDefault = null;
        public static readonly string NoFileName = null;
        public static readonly int NoLine = Parser.UnknownLine;
        public static readonly bool NoViaSource = false;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Private Constructors
#if CACHE_ARGUMENT_TOSTRING
        [DebuggerStepThrough()]
        private Argument(
            ArgumentFlags flags,
            string name,
            object value,
            object @default,
            string fileName,
            int startLine,
            int endLine,
            bool viaSource
            )
            : this(flags, name, value, NoString, @default, fileName,
                   startLine, endLine, viaSource)
        {
            // do nothing.
        }
#endif

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private Argument(
            ArgumentFlags flags,
            string name,
            object value,
#if CACHE_ARGUMENT_TOSTRING
            string @string,
#endif
            object @default,
            string fileName,
            int startLine,
            int endLine,
            bool viaSource
            )
        {
            this.flags = flags;
            this.name = name;
            this.value = value;

#if CACHE_ARGUMENT_TOSTRING
            this.@string = @string;
#endif

            this.@default = @default;
            this.fileName = fileName;
            this.startLine = startLine;
            this.endLine = endLine;
            this.viaSource = viaSource;
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        internal Argument(
            ArgumentFlags flags,
            string name,
            object value,
            object @default
            )
            : this(flags, name, value, @default, NoFileName, NoLine, NoLine,
                   NoViaSource)
        {
            // do nothing.
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        internal Argument(
            ArgumentFlags flags,
            string name,
            object value
            )
            : this(flags, name, value, NoDefault, NoFileName, NoLine, NoLine,
                   NoViaSource)
        {
            // do nothing.
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        internal Argument(
            ArgumentFlags flags,
            string name
            )
            : this(flags, name, NoValue, NoDefault, NoFileName, NoLine, NoLine,
                   NoViaSource)
        {
            // do nothing.
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        internal Argument(
            object value
            )
            : this(NoFlags, NoName, value, NoDefault, NoFileName, NoLine,
                   NoLine, NoViaSource)
        {
            // do nothing.
        }

        ///////////////////////////////////////////////////////////////////////

#if false
        [DebuggerStepThrough()]
        private Argument(
            Argument value
            )
            : this((value != null) ? value.Flags : NoFlags,
                   (value != null) ? value.Name : NoName,
                   (value != null) ? value.Value : NoValue,
                   (value != null) ? value.Default : NoDefault,
                   (value != null) ? value.FileName : NoFileName,
                   (value != null) ? value.StartLine : NoLine,
                   (value != null) ? value.EndLine : NoLine,
                   (value != null) ? value.ViaSource : NoViaSource)
        {
            // do nothing.
        }
#endif

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        internal Argument(
            Result value
            )
            : this(NoFlags, NoName, (value != null) ? value.Value : null,
                   NoDefault, NoFileName, NoLine, NoLine, NoViaSource)
        {
            // do nothing.
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        internal Argument(
            Result value,
            string fileName,
            int startLine,
            int endLine,
            bool viaSource
            )
            : this(NoFlags, NoName, (value != null) ? value.Value : null,
#if CACHE_ARGUMENT_TOSTRING
#if CACHE_RESULT_TOSTRING
                   (value != null) ? value.CachedString : null,
#else
                   null,
#endif
#endif
                   NoDefault, fileName, startLine, endLine, viaSource)
        {
            // do nothing.
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Private Methods
        internal void ResetValue(
            Interpreter interpreter,
            bool zero
            )
        {
#if !MONO && NATIVE && WINDOWS
            ReturnCode zeroCode;
            Result zeroError = null;

            if (zero && (value is string) && (interpreter != null) &&
                interpreter.HasZeroString())
            {
                zeroCode = StringOps.ZeroString(
                    (string)value, ref zeroError);

                if (zeroCode != ReturnCode.Ok)
                    DebugOps.Complain(interpreter, zeroCode, zeroError);
            }
#endif

            value = null;

#if CACHE_ARGUMENT_TOSTRING
#if !MONO && NATIVE && WINDOWS
            if (zero && (@string != null) && (interpreter != null) &&
                interpreter.HasZeroString())
            {
                zeroCode = StringOps.ZeroString(
                    @string, ref zeroError);

                if (zeroCode != ReturnCode.Ok)
                    DebugOps.Complain(interpreter, zeroCode, zeroError);
            }
#endif

            @string = null;
#endif
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Static String Helpers
        #region Dead Code
#if DEAD_CODE
        [DebuggerStepThrough()]
        private static int Compare(
            Argument argument1,
            Argument argument2,
            StringComparison comparisonType
            )
        {
            return String.Compare(ToString(argument1, null),
                ToString(argument2, null), comparisonType);
        }
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Static Conversion Helpers
        [DebuggerStepThrough()]
        private static int GetLength(
            Argument argument,
            object value,
            int @default
            )
        {
            if (value is string)
            {
                return ((string)value).Length;
            }
            else if (value != null)
            {
#if CACHE_ARGUMENT_TOSTRING
                if (argument != null)
                {
                    string @string = argument.@string;

                    if (@string != null)
                        return @string.Length;

                    @string = value.ToString();
                    argument.@string = @string;

                    if (@string != null)
                        return @string.Length;
                    else
                        return @default;
                }
                else
#endif
                {
                    return value.ToString().Length;
                }
            }
            else
            {
                return @default;
            }
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static string ToString(
            Argument argument,
            object value,
            string @default
            )
        {
            if (value is string)
            {
                return (string)value;
            }
            else if (value != null)
            {
#if CACHE_ARGUMENT_TOSTRING
                if (argument != null)
                {
                    string @string = argument.@string;

                    if (@string != null)
                        return @string;

                    @string = value.ToString();
                    argument.@string = @string;

                    return @string;
                }
                else
#endif
                {
                    return value.ToString();
                }
            }
            else
            {
                return @default;
            }
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static bool IsSupported(
            Type type
            )
        {
            if (type == null)
                return false;

            if (type == typeof(bool))
            {
                return true;
            }
            else if (type == typeof(byte))
            {
                return true;
            }
            else if (type == typeof(char))
            {
                return true;
            }
            else if (type == typeof(int))
            {
                return true;
            }
            else if (type == typeof(long))
            {
                return true;
            }
            else if (type == typeof(double))
            {
                return true;
            }
            else if (type == typeof(decimal))
            {
                return true;
            }
            else if (type == typeof(string))
            {
                return true;
            }
            else if (type == typeof(DateTime))
            {
                return true;
            }
            else if (type == typeof(TimeSpan))
            {
                return true;
            }
            else if (type == typeof(Guid))
            {
                return true;
            }
            else if (type == typeof(Uri))
            {
                return true;
            }
            else if (type == typeof(Version))
            {
                return true;
            }
            else if (type == typeof(StringBuilder))
            {
                return true;
            }
            else if (type == typeof(Result))
            {
                return true;
            }
            else if (type == typeof(ByteList))
            {
                return true;
            }
            else if (type == typeof(ResultList))
            {
                return true;
            }
            else if (type.IsEnum)
            {
                return true;
            }
            else if (type.GetInterface(typeof(IStringList).FullName) != null)
            {
                return true;
            }
            else if (type.Equals(typeof(Exception)) ||
                type.IsSubclassOf(typeof(Exception)))
            {
                return true;
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////

        /* INTERNAL STATIC OK */
        [DebuggerStepThrough()]
        internal static Argument FromObject(
            object value,
            bool forceCopy,
            bool supportedOnly,
            bool toString
            )
        {
            if (value == null)
                return null;

            Argument argument = value as Argument;

            if (argument != null)
            {
                //
                // NOTE: Otherwise, use the existing reference.
                //
                if (forceCopy)
                {
                    argument = new Argument(
                        argument.Flags, argument.Name, argument.Value,
                        argument.Default, argument.FileName,
                        argument.StartLine, argument.EndLine,
                        argument.ViaSource); /* COPY */
                }
            }
            else if (!supportedOnly || IsSupported(value.GetType()))
            {
                argument = new Argument(value); /* WRAP */
            }
            else if (toString)
            {
                argument = StringOps.GetStringFromObject(value); /* String */
            }

            return argument;
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromResult(
            Result value
            )
        {
            return new Argument(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromDouble(
            double value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromDecimal(
            decimal value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromEnum(
            Enum value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromException(
            Exception value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromVersion(
            Version value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromResultList(
            ResultList value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromStringBuilder(
            StringBuilder value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromWideInteger(
            long value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromInteger(
            int value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        /* INTERNAL STATIC OK */
        [DebuggerStepThrough()]
        internal static Argument FromBoolean(
            bool value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        /* INTERNAL STATIC OK */
        [DebuggerStepThrough()]
        internal static Argument FromCharacter(
            char value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        /* INTERNAL STATIC OK */
        [DebuggerStepThrough()]
        internal static Argument FromCharacters(
            char? value1,
            char? value2
            )
        {
            return new Argument((object)String.Format("{0}{1}",
                (value1 != null) ? value1.ToString() : null,
                (value2 != null) ? value2.ToString() : null));
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromDateTime(
            DateTime value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromTimeSpan(
            TimeSpan value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromGuid(
            Guid value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromUri(
            Uri value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        /* INTERNAL STATIC OK */
        [DebuggerStepThrough()]
        internal static Argument FromString(
            string value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromByte(
            byte value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromByteList(
            ByteList value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Argument FromList(
            IStringList value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static Result FromDictionary(
            IDictionary value
            )
        {
            return new Argument((object)value);
        }

        ///////////////////////////////////////////////////////////////////////

        /* INTERNAL STATIC OK */
        [DebuggerStepThrough()]
        internal static Argument FromCommandBuilder(
            CommandBuilder value
            )
        {
            if (value == null)
                return null;

            return new Argument(value.GetResult());
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        private static string ToString(
            Argument argument,
            string @default
            )
        {
            if (argument == null)
                return @default;

            if (!argument.HasFlags(ArgumentFlags.ToStringMask, false))
                return ToString(argument, argument.Value, @default);

            return argument.ToString(ToStringFlags.None, @default);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Conversion Operators
        [DebuggerStepThrough()]
        public static implicit operator string(
            Argument argument
            )
        {
            return ToString(argument, null);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            Result value
            )
        {
            if (value != null)
                return FromResult(value);
            else
                return null;
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            StringList value
            )
        {
            return FromList(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            StringPairList value
            )
        {
            return FromList(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            StringDictionary value
            )
        {
            return FromDictionary(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            DateTime value
            )
        {
            return FromDateTime(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            TimeSpan value
            )
        {
            return FromTimeSpan(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            Guid value
            )
        {
            return FromGuid(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            Uri value
            )
        {
            return FromUri(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            string value
            )
        {
            return FromString(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            byte value
            )
        {
            return FromByte(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            ByteList value
            )
        {
            return FromByteList(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            char value
            )
        {
            return FromCharacter(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            double value
            )
        {
            return FromDouble(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            decimal value
            )
        {
            return FromDecimal(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            Enum value
            )
        {
            return FromEnum(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            Exception value
            )
        {
            return FromException(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            Version value
            )
        {
            return FromVersion(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            ResultList value
            )
        {
            return FromResultList(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            StringBuilder value
            )
        {
            return FromStringBuilder(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            long value
            )
        {
            return FromWideInteger(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            int value
            )
        {
            return FromInteger(value);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public static implicit operator Argument(
            bool value
            )
        {
            return FromBoolean(value);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IString Members
        [DebuggerStepThrough()]
        public int IndexOf(
            string value,
            StringComparison comparisonType
            )
        {
            return ToString(this, String.Empty).IndexOf(value, comparisonType);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public int IndexOf(
            string value,
            int startIndex,
            StringComparison comparisonType
            )
        {
            return ToString(this, String.Empty).IndexOf(
                value, startIndex, comparisonType);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public int LastIndexOf(
            string value,
            StringComparison comparisonType
            )
        {
            return ToString(this, String.Empty).LastIndexOf(
                value, comparisonType);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public int LastIndexOf(
            string value,
            int startIndex,
            StringComparison comparisonType
            )
        {
            return ToString(this, String.Empty).LastIndexOf(
                value, startIndex, comparisonType);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string Substring(
            int startIndex
            )
        {
            return ToString(this, String.Empty).Substring(startIndex);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string Substring(
            int startIndex,
            int length
            )
        {
            return ToString(this, String.Empty).Substring(startIndex, length);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public int Compare(
            string value,
            StringComparison comparisonType
            )
        {
            return String.Compare(ToString(this, null), value, comparisonType);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public int Compare(
            Argument value,
            StringComparison comparisonType
            )
        {
            return String.Compare(ToString(this, null),
                ToString(value, null), comparisonType);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public bool Contains(
            string value,
            StringComparison comparisonType
            )
        {
            return (ToString(this, String.Empty).IndexOf(
                value, comparisonType) != Index.Invalid);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string Replace(
            string oldValue,
            string newValue
            )
        {
            return ToString(this, String.Empty).Replace(oldValue, newValue);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string Trim()
        {
            return ToString(this, String.Empty).Trim();
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string Trim(
            char[] trimChars
            )
        {
            return ToString(this, String.Empty).Trim(trimChars);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string TrimStart(
            char[] trimChars
            )
        {
            return ToString(this, String.Empty).TrimStart(trimChars);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string TrimEnd(
            char[] trimChars
            )
        {
            return ToString(this, String.Empty).TrimEnd(trimChars);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public char[] ToCharArray()
        {
            return ToString(this, String.Empty).ToCharArray();
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IToString Members
        [DebuggerStepThrough()]
        public string ToString(
            ToStringFlags flags
            )
        {
            return ToString(flags, null);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string ToString(
            ToStringFlags flags,
            string @default
            )
        {
            ArgumentFlags argumentFlags = this.flags;

            ///////////////////////////////////////////////////////////////////

            if (FlagOps.HasFlags(flags, ToStringFlags.NameAndValue, true) ||
                FlagOps.HasFlags(argumentFlags, ArgumentFlags.Debug, true))
            {
                IStringList list = new StringList();

                if (!String.IsNullOrEmpty(name))
                    list.Add(name);

                list.Add(ToString(this, value, @default));

                return list.ToString();
            }

            ///////////////////////////////////////////////////////////////////

            if (!FlagOps.HasFlags(
                    argumentFlags, ArgumentFlags.NameOnly, true))
            {
                return ToString(this, value, @default);
            }

            ///////////////////////////////////////////////////////////////////

            if (FlagOps.HasFlags(flags, ToStringFlags.Decorated, true))
            {
                if (FlagOps.HasFlags(
                        argumentFlags, ArgumentFlags.ArgumentList, true))
                {
                    return "?arg ...?";
                }
                else if (FlagOps.HasFlags(
                        argumentFlags, ArgumentFlags.HasDefault, true))
                {
                    return (name != null) ?
                        String.Format("?{0}?", name) : @default;
                }
            }

            ///////////////////////////////////////////////////////////////////

            return (name != null) ? name : @default;
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string ToString(
            string format
            )
        {
            return String.Format(format, name, ToString(this, null));
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public string ToString(string format, int limit, bool strict)
        {
            return FormatOps.Ellipsis(
                String.Format(format, name, ToString(this, null)), limit,
                strict);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region System.Object Overrides
        [DebuggerStepThrough()]
        public override string ToString()
        {
            return ToString(ToStringFlags.None, String.Empty);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IGetValue Members
        private object value;
        public object Value
        {
            [DebuggerStepThrough()]
            get { return value; }
        }

        ///////////////////////////////////////////////////////////////////////

#if CACHE_ARGUMENT_TOSTRING
        private string @string; /* CACHE */
        internal string CachedString
        {
            [DebuggerStepThrough()]
            get { return @string; }
        }
#endif

        ///////////////////////////////////////////////////////////////////////

        public string String
        {
            [DebuggerStepThrough()]
            get
            {
                if (HasFlags(ArgumentFlags.ToStringMask, false))
                    return ToString(ToStringFlags.None, null);
                else
                    return ToString(this, value, null);
            }
        }

        ///////////////////////////////////////////////////////////////////////

        public int Length
        {
            [DebuggerStepThrough()]
            get
            {
                if (HasFlags(ArgumentFlags.ToStringMask, false))
                {
                    string result = ToString(ToStringFlags.None, null);
                    return (result != null) ? result.Length : 0;
                }
                else
                {
                    return GetLength(this, value, 0);
                }
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IHaveClientData Members
        private IClientData clientData;
        public IClientData ClientData
        {
            [DebuggerStepThrough()]
            get { return clientData; }
            [DebuggerStepThrough()]
            set { clientData = value; }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IValueData Members
        private IClientData valueData;
        public IClientData ValueData
        {
            [DebuggerStepThrough()]
            get { return valueData; }
            [DebuggerStepThrough()]
            set { valueData = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        private IClientData extraData;
        public IClientData ExtraData
        {
            [DebuggerStepThrough()]
            get { return extraData; }
            [DebuggerStepThrough()]
            set { extraData = value; }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IArgument Members
        private string name;
        public string Name
        {
            [DebuggerStepThrough()]
            get { return name; }
            [DebuggerStepThrough()]
            set { name = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        private ArgumentFlags flags;
        public ArgumentFlags Flags
        {
            [DebuggerStepThrough()]
            get { return flags; }
            [DebuggerStepThrough()]
            set { flags = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        private object @default;
        public object Default
        {
            [DebuggerStepThrough()]
            get { return @default; }
            [DebuggerStepThrough()]
            set { @default = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public void Reset(
            bool full
            )
        {
            if (full)
            {
                flags = ArgumentFlags.None;
                name = null;
                value = null;
                @default = null;
            }
            else
            {
                flags = NoFlags;
                name = NoName;
                value = NoValue;
                @default = NoDefault;
            }
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public bool HasFlags(
            ArgumentFlags hasFlags,
            bool all
            )
        {
            return FlagOps.HasFlags(flags, hasFlags, all);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public ArgumentFlags SetFlags(
            ArgumentFlags flags,
            bool set
            )
        {
            if (set)
                return (this.flags |= flags);
            else
                return (this.flags &= ~flags);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IScriptLocation Members
        private string fileName;
        public string FileName
        {
            [DebuggerStepThrough()]
            get { return fileName; }
            [DebuggerStepThrough()]
            set { fileName = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        private int startLine;
        public int StartLine
        {
            [DebuggerStepThrough()]
            get { return startLine; }
            [DebuggerStepThrough()]
            set { startLine = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        private int endLine;
        public int EndLine
        {
            [DebuggerStepThrough()]
            get { return endLine; }
            [DebuggerStepThrough()]
            set { endLine = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        private bool viaSource;
        public bool ViaSource
        {
            [DebuggerStepThrough()]
            get { return viaSource; }
            [DebuggerStepThrough()]
            set { viaSource = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public StringPairList ToList()
        {
            return ToList(false);
        }

        ///////////////////////////////////////////////////////////////////////

        [DebuggerStepThrough()]
        public StringPairList ToList(bool scrub)
        {
            StringPairList list = new StringPairList();

            list.Add("Flags", this.Flags.ToString());
            list.Add("Name", this.Name);
            list.Add("Value", ToString(this, this.Value, null));
            list.Add("Default", StringOps.GetStringFromObject(this.Default));

            list.Add("FileName", scrub ? PathOps.ScrubPath(
                GlobalState.GetBasePath(), this.FileName) : this.FileName);

            list.Add("StartLine", this.StartLine.ToString());
            list.Add("EndLine", this.EndLine.ToString());
            list.Add("ViaSource", this.ViaSource.ToString());

            return list;
        }
        #endregion
    }
}
