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

#if !WASM
namespace CommonHelpers {
#else
namespace CommonHelpers.WASM {
#endif

//**************************************************************************************************
/// <summary>
/// </summary>
public partial class HFromOneListIndexer<T> {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[HLockFree]
public bool IsStrictReadonly
{
   get { return _IsStrictReadonly_; }
}

public bool CanBeMadeStrictReadonly
{
   get { return _CanBeMadeStrictReadonly_; }
}

[HLockFree]
public bool IsSynchronized
{
   get { return _IsSynchronized_; }
}

public object SyncRoot
{
   get { return _SyncRoot_; }
}

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

public List<T> ListCopy
{
   get { return Access(delegate{
      return new List<T>( _List_ );
   });}
}

public int Count
{
   get { return Access(delegate{
      return _List_.Count;
   });}
}

/// <exception cref="ArgumentOutOfRangeException" />
public int Capacity
{
   get { return Access(delegate{
      return _List_.Capacity;
   });}
   set { Access(true,delegate{
      _List_.Capacity = value;
   });}
}

/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="HReadonlyObjectAccessException" />
public T this[int oneBasedIdx]
{
   get { return Access(delegate{
      return _List_[ oneBasedIdx-1 ];
   });}
   set { Access(true,delegate{
      _List_[ oneBasedIdx-1 ] = value;
   });}
}

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

public static implicit operator List<T> ( HFromOneListIndexer<T> indexer )
{
   return indexer.ListCopy;
}

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

public HFromOneListIndexer()
   :this ( true ) {}

public HFromOneListIndexer(bool canBeMadeStrictReadonly)
   :this ( new List<T>() )
{
   _CanBeMadeStrictReadonly_ = canBeMadeStrictReadonly;
}

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

/// <exception cref="ArgumentNullException" />
public HFromOneListIndexer(IEnumerable<T> collection,bool canBeMadeStrictReadonly=true)
   :this ( new List<T>( collection ), canBeMadeStrictReadonly ) {}

/// <exception cref="ArgumentOutOfRangeException" />
public HFromOneListIndexer(int capacity,bool canBeMadeStrictReadonly=true)
   :this ( new List<T>( capacity ), canBeMadeStrictReadonly ) {}

/// <exception cref="ArgumentNullException" />
public HFromOneListIndexer(List<T> list,bool canBeMadeStrictReadonly=true)
{
   HArgChecking.VerifyNotNull( list );
   _List_ = list;
   _CanBeMadeStrictReadonly_ = canBeMadeStrictReadonly;
}

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

/// <exception cref="InvalidOperationException" />
public HFromOneListIndexer<T> MakeStrictReadonly()
{
   if ( !CanBeMadeStrictReadonly )
      throw new InvalidOperationException( "The collection can not be made strict readonly." );
   lock ( SyncRoot )
      _IsStrictReadonly_ = true;
   return this;
}

/// <exception cref="InvalidOperationException" />
public HFromOneListIndexer<T> MakeSynchronized()
{
   Access(true,delegate{ _IsSynchronized_ = true; });
   return this;
}

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

public override string ToString()
{
   return Access(delegate{
      return _List_.ToString();
   });
}

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

public virtual HFromOneListIndexer<T> Duplicate()
{
   return Access(delegate{
      var instance = new HFromOneListIndexer<T>( _List_ );
      return IsSynchronized ? instance.MakeSynchronized() : instance;
   });
}

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

/// <exception cref="ArgumentOutOfRangeException" />
public static HFromOneListIndexer<T> CreateWithLength(int length)
{
   return CreateWithLength( length, default(T) );
}

/// <exception cref="ArgumentOutOfRangeException" />
public static HFromOneListIndexer<T> CreateWithLength(int length,T value)
{
   var indexer = new HFromOneListIndexer<T>( length );
   HOps.Repeat( length, delegate { indexer.Add( value ); } );
   return indexer;
}

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

/// <exception cref="HReadonlyObjectAccessException" />
protected List<T> BaseList
{
   get { return _List_; }
}

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

/// <exception cref="HReadonlyObjectAccessException" />
protected void DenyReadonlyAccess()
{
   if ( IsStrictReadonly ) throw new HReadonlyObjectAccessException();
}

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

protected void Access(Action callback)
{
   Access( false, callback );
}
protected R Access<R>(Func<R> callback)
{
   return Access( false, callback );
}

protected void Access(bool denyReadonlyAccess,Action callback)
{
   if ( denyReadonlyAccess ) DenyReadonlyAccess();
   HConditionalLock.LockIf( IsSynchronized, SyncRoot, callback );
}
protected R Access<R>(bool denyReadonlyAccess,Func<R> callback)
{
   if ( denyReadonlyAccess ) DenyReadonlyAccess();
   return HConditionalLock.LockIf( IsSynchronized, SyncRoot, callback );
}

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

static HFromOneListIndexer()
{
   CommonHelpers_Core.Access();
}

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

readonly object
   _SyncRoot_ = new object();
readonly List<T>
   _List_;
readonly bool
   _CanBeMadeStrictReadonly_;
volatile bool
   _IsStrictReadonly_, _IsSynchronized_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HFromOneListIndexer
//**************************************************************************************************

} // CommonHelpers (.WASM)
