using AntiAircraftGun.CollectionGenericObjects;
using AntiAircraftGun.Drawnings;
using AntiAircraftGun.Exceptions;

namespace AntiAircraftGun.CollectionGenereticObject;

/// <summary>
/// Параметризованный набор объектов
/// </summary>
/// <typeparam name="T">Параметр: ограничение - ссылочный тип</typeparam>
public class MassiveGenericObjects<T> : ICollectionGenericObjects<T>
    where T : class
{
    /// <summary>
    /// Массив объектов, которые храним
    /// </summary>
    private T?[] _collection;

    public int Count => _collection.Length;

    public int MaxCount
    {
        get
        {
            return _collection.Length;
        }
        set
        {
            if (value > 0)
            {
                if (_collection.Length > 0)
                {
                    Array.Resize(ref _collection, value);
                }
                else
                {
                    _collection = new T?[value];
                }
            }
        }
    }

    public CollectionType GetCollectionType => CollectionType.Massive;

    /// <summary>
    /// Конструктор
    /// </summary>
    public MassiveGenericObjects()
    {
        _collection = Array.Empty<T?>();
    }

    public T? Get(int position)
    {
        if (position < 0 || position >= Count) throw new PositionOutOfCollectionException(position);
        if (_collection[position] == null) throw new ObjectNotFoundException(position);
        return _collection[position];
 
    }

    public int Insert(T obj)
    {
        
        for (int i = 0; i < Count; i++)
        {
            if (_collection[i] == null)
            {
                _collection[i] = obj;
                return i;
            }
        }

        throw new CollectionOverflowException(Count);
    }

    public int Insert(T obj, int position)
    {

        if (position >= Count || position < 0) throw new PositionOutOfCollectionException(position);
        if (_collection[position] != null)
        {
            bool pushed = false;
            for (int index = position + 1; index < Count; index++)
            {
                if (_collection[index] == null)
                {
                    position = index;
                    pushed = true;
                    break;
                }
            }

            if (!pushed)
            {
                for (int index = position - 1; index >= 0; index--)
                {
                    if (_collection[index] == null)
                    {
                        position = index;
                        pushed = true;
                        break;
                    }
                }
            }

            if (!pushed)
            {
                throw new CollectionOverflowException(Count);
            }
        }

        // вставка
        _collection[position] = obj;
        return position;
    }

    public T? Remove(int position)
    {
        if (position < 0 || position >= Count) throw new PositionOutOfCollectionException(position);

        if (_collection[position] == null) throw new ObjectNotFoundException(position);

        T? temp = _collection[position];
        _collection[position] = null;
        return temp;
    }

    public IEnumerable<T?> GetItems()
    {
        for (int i = 0; i < _collection.Length; ++i)
        {
            yield return _collection[i];
        }
    }
}