#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
namespace imm;
///
/// An immutable list implementation that tracks history, metadata, and time.
///
public record class List : Timed>, IImmutableList
{
static public List Empty { get; } = new();
public ImmutableList Values { get; init; } = ImmutableList.Empty;
public List() { }
// Required for 'with' expressions to work with the base class hierarchy
protected List(Timed> original) : base(original) { }
// Helper to apply changes using the Process method
private List Change(
Func, ImmutableList> listChange,
[CallerMemberName] string dbgMethod = "",
[CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = -1,
[CallerArgumentExpression( "listChange" )] string reason = "" )
{
var newValues = listChange(Values);
return ReferenceEquals(Values, newValues)
? this
: Process(l => l with { Values = newValues }, reason, dbgMethod, dbgPath, dbgLine, reason);
}
// --- IImmutableList implementation using the Change helper ---
public T this[int index] => Values[index];
public int Count => Values.Count;
public List Add(T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.Add(value), dbgMethod, dbgPath, dbgLine);
public List AddRange(IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.AddRange(items), dbgMethod, dbgPath, dbgLine);
public List Clear([CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.Clear(), dbgMethod, dbgPath, dbgLine);
#region IImmutableList Implementati, dbgMethod, dbgPath, dbgLineon
public List Insert( int index, T element, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Insert( index, element ) , dbgMethod, dbgPath, dbgLine);
public List InsertRange( int index, IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.InsertRange( index, items ) , dbgMethod, dbgPath, dbgLine);
public List Remove( T value, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Remove( value, equalityComparer ) , dbgMethod, dbgPath, dbgLine);
public List Remove( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Remove( value, EqualityComparer.Default , dbgMethod, dbgPath, dbgLine);
public List RemoveAll( Predicate match, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAll( match ) , dbgMethod, dbgPath, dbgLine);
public List RemoveAt( int index, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAt( index ) , dbgMethod, dbgPath, dbgLine);
public List RemoveRange( int index, int count, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( index, count ) , dbgMethod, dbgPath, dbgLine);
public List RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( items, equalityComparer ) , dbgMethod, dbgPath, dbgLine);
public List Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Replace( oldValue, newValue, equalityComparer ) , dbgMethod, dbgPath, dbgLine);
public List SetItem( int index, T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.SetItem( index, value ) , dbgMethod, dbgPath, dbgLine);
public int IndexOf( T item, int index, int count, IEqualityComparer? equalityComparer ) => Values.IndexOf( item, index, count, equalityComparer ?? EqualityComparer.Default );
public int LastIndexOf( T item, int index, int count, IEqualityComparer? equalityComparer) => Values.LastIndexOf( item, index, count, equalityComparer ?? EqualityComparer.Default );
public int IndexOf( T item, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => IndexOf( item, 0, Count, EqualityComparer.Default);
IImmutableList IImmutableList.Clear() => Clear();
IImmutableList IImmutableList.Add( T value ) => Add( value );
IImmutableList IImmutableList.AddRange( IEnumerable items ) => AddRange( items );
IImmutableList IImmutableList.Insert( int index, T element ) => Insert( index, element );
IImmutableList IImmutableList.InsertRange( int index, IEnumerable items ) => InsertRange( index, items );
IImmutableList IImmutableList.Remove( T value, IEqualityComparer? equalityComparer ) => Remove( value, equalityComparer );
IImmutableList IImmutableList.RemoveAll( Predicate match ) => RemoveAll( match );
IImmutableList IImmutableList.RemoveAt( int index ) => RemoveAt( index );
IImmutableList IImmutableList.RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer ) => RemoveRange( items, equalityComparer );
IImmutableList IImmutableList.RemoveRange( int index, int count ) => RemoveRange( index, count );
IImmutableList IImmutableList.Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer ) => Replace( oldValue, newValue, equalityComparer );
IImmutableList IImmutableList.SetItem( int index, T value ) => SetItem( index, value );
#endregion
// --- Standard Interfaces ---
public IEnumerator GetEnumerator() => Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)Values).GetEnumerator();
}