using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VisimBox.Resources;

namespace VisimBox.Renderer
{
    /// <summary>
    /// Abstract interface for HW renderer buffers (used for index and vertex buffers)
    /// </summary>
    /// <typeparam name="T">Either uint (index buffer) or IVertex</typeparam>
    public interface IHWBuffer<T> : IResource
    {
        /// <summary>
        /// Allows access to buffer elements array style. If caching is enabled, reads/writes from cache, otherwise uses direct (and usually slow) access.
        /// </summary>
        /// <param name="index">index of the element</param>
        /// <returns></returns>
        T this[int index] { get; set; }

        /// <summary>
        /// Number of elements in the buffer
        /// </summary>
        int Count { get; }

        /// <summary>
        /// Internal ID for the buffer
        /// </summary>
        uint InternalID { get; }

        /// <summary>
        /// If cached, index buffer will keep copy of the data in the system memory.
        /// All user read / write operations will be routed to cached copy. 
        /// Use ReadCache / WriteCache to update buffer
        /// </summary>
        bool Cached { get; set; }

        /// <summary>
        /// Reads content of the buffer to cache
        /// </summary>
        void ReadCache();

        /// <summary>
        /// Reads part of the buffer to cache
        /// </summary>
        /// <param name="start">starting index</param>
        /// <param name="count">number of elements to be read from the buffer</param>
        void ReadCache(int start, int count);

        /// <summary>
        /// Writes content of the cache to index buffer
        /// </summary>
        void WriteCache();

        /// <summary>
        /// Writes content of the cache to the buffer
        /// </summary>
        /// <param name="start">starting index</param>
        /// <param name="count">number of elements to be written to the buffer</param>
        void WriteCache(int start, int count);

        /// <summary>
        /// Directly reads one element from the buffer (might be very slow)
        /// </summary>
        /// <param name="position">Index of the element to write</param>
        /// <returns>Element on the position</returns>
        T ReadElement(int position);

        /// <summary>
        /// Directly reads several elements from the buffer (might be very slow)
        /// </summary>
        /// <param name="position">Starting position</param>
        /// <param name="count">Number of elements</param>
        /// <returns>Array of elements from the buffer</returns>
        T[] ReadElements(int position, int count);

        /// <summary>
        /// Directly reads several elements from the buffer (might be very slow) to specified array
        /// </summary>
        /// <param name="position">Starting position</param>
        /// <param name="count">Number of elements</param>
        /// <param name="dest">Destination array (will be created if null)</param>
        /// <param name="start">Starting index in the array </param>
        void ReadElements(int position, int count, ref T[] dest, int start = 0);

        /// <summary>
        /// Directly writes element to the buffer
        /// </summary>
        /// <param name="position">Position of element</param>
        /// <param name="value">New value for buffer</param>
        void WriteElement(int position, ref T value);

        /// <summary>
        /// Directly writes array of elements to the buffer)
        /// </summary>
        /// <param name="position">Position of element</param>
        /// <param name="values">Array of elements</param>
        void WriteElements(int position, T[] values);


        /// <summary>
        /// Directly writes part of the array of elements to the buffer)
        /// </summary>
        /// <param name="position">Position of element</param>
        /// <param name="values">Array of elements</param>
        /// <param name="count">Number of elements to write</param>
        /// <param name="start">Starting position in the source array</param>
        void WriteElements(int position, T[] values, int start, int count);
    }
}
