//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;

namespace CommonHelpers {

//**************************************************************************************************
/// <summary>
/// </summary>
public partial class HCmdLineParameter {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[HNotNull]
public string Value { get; private set; }
[HOptionalValue]
public string NakedValue { get; private set; }

[HOptionalValue]
public string SwitchKey { get; private set; }
public bool HasSwitchKey { get { return SwitchKey != null; } }
public bool IsHyphenSwitch { get; private set; }

public bool HasArgumentationSign { get { return NakedSwitchKeyArguments != null; } }

public bool HasSwitchKeyArguments
{
   get { return SwitchKeyArgumentCount > 0; }
}
public int SwitchKeyArgumentCount
{
   get { return HasArgumentationSign ? NakedSwitchKeyArguments.Length : 0; }
}

[HOneBasedIndex]
public int AbsoluteStartPosition { get; private set; }
[HOneBasedIndex]
public int RelativeStartPosition { get; private set; }

[HOptionalValue]
public HCmdLineKeyDefinition KeyDefinition { get; private set; }

//--------------------------------------------------------------------------------------------------

/// <exception cref="InvalidOperationException" />
public string SwitchKeyWithSign
{
   get
   {
      if ( SwitchKey == null )
         throw new InvalidOperationException();
      string switchKey = KeyDefinition != null ?
         KeyDefinition.SwitchKey : SwitchKey;
      return ( IsHyphenSwitch ?
         HCmdLineParametersParser.SwitchCharacterHyphen :
         HCmdLineParametersParser.SwitchCharacterSlash ) +
         switchKey;
   }
}

//--------------------------------------------------------------------------------------------------

/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
public string this[int switchArgumentIdx]
{
   get
   {
      if ( !HasArgumentationSign )
         throw new InvalidOperationException();
      return NakedSwitchKeyArguments[ switchArgumentIdx ];
   }
}

//==================================================================================================

[HOptionalValue]
protected internal string[] NakedSwitchKeyArguments { get; private set; }

//==================================================================================================

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="ArgumentException" />
internal HCmdLineParameter( int absoluteStartZeroBasedPos,
                            int relativeStartZeroBasedPos,
                            string value, string nakedValue,
                            [HRelOpt] string switchKey,
                            bool isHyphenSwitch,
                            [HOptional] string[] nakedSwitchArguments,
                            [HOptional] HCmdLineKeyDefinition keyDefinition )
{
   if ( absoluteStartZeroBasedPos < 0 )
      throw new ArgumentOutOfRangeException(
         "absoluteStartZeroBasedPos",
         "Parameter start absolute position (in full command line) must not be negative." );
   if ( relativeStartZeroBasedPos < 0 )
      throw new ArgumentOutOfRangeException(
         "relativeStartZeroBasedPos",
         "Relative parameter start position (in parameters part of the command line) "+
         "must not be negative." );
   if ( relativeStartZeroBasedPos > absoluteStartZeroBasedPos )
      throw new ArgumentException(
         "Relative parameter start position (in parameters part of the command line) "+
         "can not be greater than absolute parameter start position (in full command line).",
         "relativeStartZeroBasedPos");

   if ( value == null )
      throw new ArgumentNullException( "value" );
   if ( HString.IsBlank( value ) )
      throw new ArgumentException( "Value parameter must not be blank.", "value" );
   if ( HString.HasBoundaryWhiteSpace( value ) )
      throw new ArgumentException( "Value parameter must not have bound whitespaces.", "value" );
   Value = value;

   if ( nakedValue == null )
      throw new ArgumentNullException( "nakedValue" );
   NakedValue = nakedValue;

   if ( switchKey != null )
   {
      if ( HString.IsBlank( switchKey ) )
         throw new ArgumentException(
            "Switch key parameter (if specified) must not be blank.", "switchKey" );
      if ( HString.ContainsWhiteSpace( switchKey ) )
         throw new ArgumentException(
            "Switch key parameter must not contain whitespaces.", "switchKey" );
      SwitchKey = switchKey;
   }

   if ( isHyphenSwitch && switchKey == null )
      throw new ArgumentException(
         "Specification of \"isHyphenSwitch\" parameter requires not null value "+
         "for \"switchKey\" parameter.", "isHyphenSwitch" );
   IsHyphenSwitch = isHyphenSwitch;

   if ( nakedSwitchArguments != null )
   {
      if ( switchKey == null )
         throw new ArgumentNullException( "nakedSwitchArguments",
            "Specification of \"nakedSwitchArguments\" parameter requires not null value "+
            "for \"switchKey\" parameter." );
      char quoteChar = HCmdLineParametersParser.ParamQuoteCharacter;
      foreach (string arg in nakedSwitchArguments)
      {
         if ( arg == null )
            throw new ArgumentException(
               "Switch arguments parameter (if specified) must not have null array values.",
               "nakedSwitchArguments" );
         if ( HString.HasBoundaryWhiteSpace( arg ) )
            throw new ArgumentException(
               "Switch arguments parameter (if specified) must not have array values "+
               "with bound whitespaces.", "nakedSwitchArguments" );
         if ( HString.StartsWith( arg, quoteChar ) &&
              ( arg.Length == 1 || !HString.EndsWith( arg, quoteChar ) ) )
            throw new ArgumentException(
               "Incorrect quotation embracement for array value of switch argument.",
               "nakedSwitchArguments" );
      }
      NakedSwitchKeyArguments = nakedSwitchArguments;
   }

   if ( keyDefinition != null && switchKey == null )
      throw new ArgumentException(
         "Specification of \"keyDefinition\" parameter requires not null value "+
         "for \"switchKey\" parameter.", "keyDefinition" );
   KeyDefinition = keyDefinition;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HCmdLineParameter
//**************************************************************************************************

} // CommonHelpers
