using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VisiMath;
using VisiMath.Geometry;

namespace VisimBox.Renderer.RenderObjects
{
    //rendering - fist pass asks for renderbuffers
    //sorts render buffers
    //renders in order: prepares materials using render to texture
    // non lighted simple materials (unsorted or front to back), lighted materials (unsorted or front to back), alpha materials (sorted back to front)
    
    /// <summary>
    /// Nodes and any other object which can be rendered must implent this interface
    /// </summary>
    public interface IRenderable
    {
        
        /// <summary>
        /// Returns bounding object of the renderable item (for lights etc). Should be simplest possible (box)
        /// </summary>
        /// <returns>Bounding object or null if not using one</returns>
        IGeometry GetBoundingObject();

        /// <summary>
        /// Fallback function if GetBoundingObject returns null.
        /// </summary>
        /// <returns>Center of the object</returns>
        Vector3 GetCenter();

        
        /// <summary>
        /// Called by the renderer when rendering hiearchy of elements.
        /// Object must either perform complete render (set transformation, material and use direct rendering calls)
        /// or feed renderbuffer of the context with correct data.
        /// </summary>
        /// <param name="args">Rendering events - pointer to rendering context and renderer</param>
        /// <remarks>Direct rendering should be done only in special cases in this call as it removes any rendering optimalizations performed 
        /// on the render buffer. This is important especially for any objects using alpha transparency, which could create visual artefacts unless rendered
        /// in sorter back to front order.</remarks>
        void OnRender(RendererEventArgs args);

        /// <summary>
        /// Feed geometry to the renderer (all other settings should be already set)
        /// </summary>
        /// <param name="args">Rendering events - pointer to rendering context and renderer</param>
        /// <remarks>Used when rendering from the renderbuffer</remarks>
        void RenderGeometry(RendererEventArgs args);
    }

    /// <summary>
    /// Render buffer item used by IRenderable for standard rendering
    /// </summary>
    public class RenderBufferItem
    {
        /// <summary>
        /// IRenderable owner of the item (for rendering geometry via RenderGeometry)
        /// </summary>
        public IRenderable Item;
        /// <summary>
        /// Required rendering material
        /// </summary>
        public IRenderMaterial Material;
        /// <summary>
        /// SQUARED distance to the camera (for sorting)
        /// </summary>
        public float CameraDistance;
        /// <summary>
        /// Does object contain alpha transparency? (REQUIRED for correct rendering, as alpha objects must be sorted)
        /// </summary>
        public bool Alpha;
        /// <summary>
        /// Spatial world transformation
        /// </summary>
        public Matrix4 Trans;        
        /// <summary>
        /// Is world transformation valid? (if false, identity will be used)
        /// </summary>
        public bool TransValid;
        //Lights
    }
}
