use crate::doomdef::SCREENWIDTH;
use crate::m_fixed::{fixed_t};
use crate::tables::angle_t;

// TODO: Implement d_think.h and p_mobj.h

/// Original Source comment: 
/// Silhouette, needed for clipping Segs (mainly)
/// and sprites representing things.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(i32)]
pub enum Silhouette {
    None = 0,
    Bottom = 1,
    Top = 2,
    Both = 3,
}

pub const MAXDRAWSEGS: i32 = 256;

/// Original source comment
/// This could be wider for >8 bit display.
/// Indeed, true color support is posibble
///  precalculating 24bpp lightmap/colormap LUT.
///  from darkening PLAYPAL to all black.
/// Could even us emore than 32 levels.
type lighttable_t = u8;

/// Original Source comment: 
/// Your plain vanilla vertex.
/// Note: transformed values not buffered locally,
///  like some DOOM-alikes ("wt", "WebView") did.
#[derive(Copy, Clone)]
pub struct vertex_t {
    x: fixed_t,
    y: fixed_t
}

/// Original Source comment: 
/// Each sector has a degenmobj_t in its center
///  for sound origin purposes.
/// I suppose this does not handle sound from
///  moving objects (doppler), because
///  position is prolly just buffered, not
///  updated.
pub struct degenmobj_t {
    //TODO: implement d_think.h
    // thinker: thinker_t,
    x: fixed_t,
    y: fixed_t,
    z: fixed_t    
}

/// Sectors represent a distinct, closed polygon area on the map with uniform 
/// floor heights, ceiling heights, lighting levels, and floor/ceiling textures.
/// They also serve as containers for gameplay entities (`mobj_t`).
/// Original Source comment: 
/// The SECTORS record, at runtime.
/// Stores things/mobjs.
pub struct sector_t {
    /// Height of the floor
    pub(crate) floorheight: fixed_t,

    /// Height of the ceiling
    pub(crate) ceilingheight: fixed_t,

    /// Texture index applied to the floor surface
    pub(crate) floorpic: i16,

    /// Texture index applied to the ceiling surface
    pub(crate) ceilingpic: i16,

    /// The current brightness level for the sector
    pub(crate) lightlevel: i16,

    /// Sector type/behaviour flags (e.g sewage / lava damaging floors)
    pub(crate) special: i16,

    /// Unique ID tag used by linedef triggers to identify and manipluate this sector
    pub(crate) tag: i16,
    
    /// Sound propagation state variable used during sound traversal calculations.
    /// Values: 0 = untraversed, 1 or 2 = sound lines - 1.
    pub(crate) soundtraversed: i32,

    //TODO: mobj_t implementation (p_mobj.h)
    /// Pointer to the map object (`mobj_t`) that generated a sound in this sector, or null.
    pub(crate) soundtarget: *mut mobj_t,

    /// A bounding box `[ymin, ymax, xmin, xmax]` mapping blocks for height changes and collisions.
    pub(crate) blockbox: [i32; 4],

    ///  simplified, stationary map object representing the central origin point for sound playback.
    pub(crate) soundorg: degenmobj_t,

    /// A frame check counter variable used to avoid re-processing this sector multiple times per tick.
    pub(crate) validcount: i32,

    /// A dynamic collection of all map objects currently inside this sector.
    /// TODO: Change back to *mut mobj_t linked list later
    pub(crate) thinglist: Vec<mobj_t>,

    /// A generic raw pointer to an active thinker struct (e.g., `plat_t`, `ceiling_t`) for handling moving parts
    pub(crate) specialdata: *mut (), 

    /// The total number of linedefs that form the boundaries of this sector.
    pub(crate) linecount: i32,

    /// A raw pointer to an array of pointers pointing to the `line_s` (linedef) structs that border this sector.
    pub(crate) lines: *mut *mut line_s, 
}

/// Linedefs are made up of either one or two sidedefs (front and back). 
/// A sidedef contains texture alignment offsets, texture indices, and 
/// points directly to the sector it faces.
pub struct sidedef_t {

    /// Horizontal alignment offset added to the calculated texture column.
    pub(crate) textureoffset: fixed_t,

     /// Vertical alignment offset added to the calculated texture top.
    pub(crate) rowoffset: fixed_t, 

    // texture indices

    /// The index of the upper wall texture (above the ceiling gap).
    pub(crate) toptexture: i16,

    /// The index of the lower wall texture (below the floor gap).
    pub(crate) bottomtexture: i16,

    /// The index of the middle wall texture (used on single-sided walls or windows).
    pub(crate) midtexture: i16,
    
    /// A raw pointer to the sector this specific side faces.
    pub(crate) sector: *mut sector_t,
}

/// The line slope classification type.
/// 
/// Used by the collision and rendering engines to optimize intersection 
/// checks and line-of-sight tracking based on the orientation of a wall line.
#[derive(Copy, Clone)]
enum slopetype_t {

    /// A perfectly horizontal line (dy == 0).
    ST_HORIZONTAL,

    /// A perfectly vertical line (dx == 0).
    ST_VERTICAL,

    /// A line with a positive slope rising from bottom-left to top-right (dx and dy have the same sign).
    ST_POSITIVE,

    /// A line with a negative slope falling from top-left to bottom-right (dx and dy have opposite signs).
    ST_NEGATIVE
}


/// Linedefs form the walls and structural geometry of a map. They contain
/// pointers to their start/end vertices, front/back siding data, physical 
/// triggers (`special`), and precalculated bounding extents to assist the physics engine.
pub struct linedef_t {
     /// Raw pointer to the starting vertex (v1) of the wall.
    pub(crate) v1: *mut vertex_t,
    
    /// Raw pointer to the ending vertex (v2) of the wall.
    pub(crate) v2: *mut vertex_t,

    /// Precalculated horizontal delta value (v2.x - v1.x) for quick side-of-line checking.
    pub(crate) dx: fixed_t,
    
    /// Precalculated vertical delta value (v2.y - v1.y) for quick side-of-line checking.
    pub(crate) dy: fixed_t,

    /// Configuration flags handling behavior (e.g., solid wall, blocks monsters, secret map wall).
    pub(crate) flags: i16,
    
    /// The linedef activation type/trigger function index (e.g., doors, teleporters, lifts).
    pub(crate) special: i16,
    
    /// A unique ID tag matching sector targets to process execution triggers.
    pub(crate) tag: i16,

    /// Sidedef lookups. `sidenum[0]` is the front side; `sidenum[1]` is the back side (or -1 if single-sided).
    pub(crate) sidenum: [i16; 2],			

    /// Bounding box layout `[ymin, ymax, xmin, xmax]` representing the full grid extent of the line.
    pub(crate) bbox: [fixed_t; 4],

    /// Slope classification used to optimize physics intersection and visibility clipping loops.
    pub(crate) slopetype: slopetype_t,

    /// Raw pointer to the sector directly in front of this linedef's first side.
    pub(crate) frontsector: *mut sector_t,
    
    /// Raw pointer to the sector behind this linedef's second side, or null if single-sided.
    pub(crate) backsector: *mut sector_t,

    /// A frame counter lookup variable used to avoid parsing or processing this line multiple times per tick.
    pub(crate) validcount: i32,

    /// A generic raw pointer to a running thinker action layout (e.g., standard scrolling wall textures).
    pub(crate) specialdata: *mut (),		
}


/// Subsectors are the structural leaves at the bottom of the BSP tree. 
/// They represent smaller, guaranteed-convex sub-polygons carved out of a 
/// larger sector, defined by a sequential slice of rendering lines (`seg_t`).
pub struct subsectordef_t {
    /// A raw pointer to the parent sector that this subsector belongs to.
    pub(crate) sector: *mut sector_t,

    /// The total number of consecutive line segments (`seg_t`) that form this subsector.
    pub(crate) numlines: i16,

    /// The starting array index inside the global `segs` array for this subsector's lines.
    pub(crate) firstline: i16,
}

/// Segs are clipped slices of linedefs generated by the node builder. 
/// The rendering engine processes them in strict front-to-back order 
/// using the BSP tree to draw wall surfaces without sorting artifacts.
pub struct segdef_t {
    /// Raw pointer to the starting vertex (v1) of this specific segment.
    pub(crate) v1: *mut vertex_t,

    /// Raw pointer to the ending vertex (v2) of this specific segment.
    pub(crate) v2: *mut vertex_t,
    
    /// The distance offset along the original linedef where this segment begins.
    pub(crate) offset: fixed_t,

    /// The absolute binary angle of the segment (represented as a 32-bit unsigned integer).
    pub(crate) angle: angle_t,

    /// Raw pointer to the sidedef structure containing the texture data for this segment.
    pub(crate) sidedef: *mut sidedef_t,

    /// Raw pointer to the parent linedef structure this segment was split out from.
    pub(crate) linedef: *mut linedef_t,

    /// Raw pointer to the sector directly in front of this segment.
    pub(crate) frontsector: *mut sector_t,

    /// Raw pointer to the sector behind this segment, or null if it belongs to a solid one-sided wall.
    pub(crate) backsector: *mut sector_t,
}

/// Nodes form the internal branching skeleton of the map's 3D visibility tree.
/// Each node acts as a cutting plane line segment that splits a sub-region into
pub struct node_t {
    /// Starting X coordinate of the division splitter line.
    pub(crate) x: fixed_t,

    /// Starting Y coordinate of the division splitter line.
    pub(crate) y: fixed_t,
    
    /// Horizontal delta length of the division splitter vector.
    pub(crate) dx: fixed_t,
    
    /// Vertical delta length of the division splitter vector.
    pub(crate) dy: fixed_t,

    /// Precalculated bounding boxes [ymin, ymax, xmin, xmax] for the right [0] and left [1] child spaces.
    pub(crate) bbox: [[FixedT; 4]; 2],

    /// References to left [0] and right [1] children. If highest bit (0x8000) is set, it targets a subsector_t index.
    pub(crate) children: [u16; 2],
}

/// A runtime record of a drawn wall segment.
/// Stores clipping and scaling metadata to correctly occlude and scale sprites behind it.
pub struct drawseg_t {
    /// Pointer to the line segment being rendered (usually seg_t).
    pub(crate) curline: *mut sector_t,

    /// Starting horizontal screen column (left boundary).
    pub(crate) x1: i32,
    
    /// Ending horizontal screen column (right boundary).
    pub(crate) x2: i32,

    /// Initial texture scale at the starting column (x1).
    pub(crate) scale1: fixed_t,

    /// Final texture scale at the ending column (x2).
    pub(crate) scale2: fixed_t,

    /// Amount to change the texture scale per horizontal pixel step.
    pub(crate) scalestep: fixed_t,

    /// Silhouette type flags handling sprite occlusion (e.g., SIL_BOTTOM, SIL_TOP).
    pub(crate) silhouette: i32,

    /// Maximum floor height boundary for bottom silhouette clipping.
    pub(crate) bsilheight: fixed_t,

    /// Minimum ceiling height boundary for top silhouette clipping.
    pub(crate) tsilheight: fixed_t,

    /// Pointer to the screen column array managing top clipping bounds for sprites.
    pub(crate) sprtopclip: *mut u16,

    /// Pointer to the screen column array managing bottom clipping bounds for sprites.
    pub(crate) sprbottomclip: *mut u16,

    /// Pointer to the column offset array used for rendering masked textures.
    pub(crate) maskedtexturecol: *mut u16,
}

/// A hardware-agnostic 2D picture or graphic asset.
/// Uses a column-oriented format to optimize rapid vertical stretching and scaling.
pub struct patch_t {
    /// Total width of the graphic patch in pixels.
    pub(crate) width: u16,
    
    /// Total height of the graphic patch in pixels.
    pub(crate) height: u16,

    /// Horizontal offset relative to the origin (used to center weapon and sprite frames).
    pub(crate) leftoffset: u16,

    /// Vertical offset relative to the origin (used to center weapon and sprite frames).
    pub(crate) topoffset: u16,

    /// Array of byte offsets from the start of the patch to the start of each vertical pixel column.
    /// only [width] used
    // the [0] is &columnofs[width] 
    pub(crate) columnofs: [i32; 8],
}

/// A visible sprite entry prepared for rendering.
/// Tracks screen bounds, scaling, and clipping parameters for a partly visible map object.
pub struct vissprite_t {
    /// Pointer to the previous sprite in the doubly linked list.
    pub(crate) prev: *mut vissprite_t,
    
    /// Pointer to the next sprite in the doubly linked list.
    pub(crate) next: *mut vissprite_t,
    
    /// Starting horizontal screen column (left boundary).
    pub(crate) x1: i32,
    
    /// Ending horizontal screen column (right boundary).
    pub(crate) x2: i32,

    /// Global X coordinate used for line-side visibility checks.
    pub(crate) gx: fixed_t,
    
    /// Global Y coordinate used for line-side visibility checks.
    pub(crate) gy: fixed_t,		

    /// Global bottom Z coordinate used for silhouette clipping calculations.
    pub(crate) gz: fixed_t,
    
    /// Global top Z coordinate used for silhouette clipping calculations.
    pub(crate) gzt: fixed_t,

    /// Horizontal texture offset fraction at screen column x1.
    pub(crate) startfrac: fixed_t,
    
    /// Scale factor of the sprite relative to its distance from the camera.
    pub(crate) scale: fixed_t,
    
    /// Horizontal step scale factor (inverted and negative if the sprite is flipped).
    pub(crate) xiscale: fixed_t,	

    /// Vertical texture alignment midpoint coordinate.
    pub(crate) texturemid: fixed_t,
    
    /// The index of the graphic patch asset being rendered.
    pub(crate) patch: i32,

    /// Pointer to the color lookup array handling lighting, shadows, and full-brightness frames.
    pub(crate) colormap: *mut lighttable_t,
   
    /// Cached copy of the parent map object's physics and state flags.
    pub(crate) mobjflags: i32,
}

/// Animation frame data for a sprite object.
/// Tracks raw graphic lump IDs and horizontal flip bits for all 8 view rotations.
#[derive(Copy, Clone)]
pub struct spriteframe_t {
    /// True if the sprite has directional rotation variants; false if it looks identical from all sides.
    pub(crate) rotate: bool,

    /// WAD graphic lump indices representing the image assets for view angles 0 to 7.
    pub(crate) lump: [i16; 8],

    /// Bitmask flags (1 = mirror image horizontally) applied to view angles 0 to 7 to save space.
    pub(crate) flip: [u8; 8],
}

/// A top-level sprite asset container managing a series of sequential animation frames.
pub struct spritedef_t {
    /// Total number of animation frames allocated for this sprite sequence.
    pub(crate) numframes: i32,

    /// Raw pointer to the array of frame records tracking rotation and asset data.
    pub(crate) spriteframes: *mut spriteframe_t,
}

/// A floor or ceiling polygon segment prepared for flat horizontal texture mapping.
/// Merges drawing spans to prevent visible gaps or layout cracking during screen refresh.
pub struct visplane_t {
    /// Absolute height level of the floor or ceiling plane in fixed-point space.
    pub(crate) height: fixed_t,

    /// WAD graphic texture flat index applied to the surface.
    pub(crate) picnum: i32,

    /// Calculated light/brightness visibility level of the flat polygon plane.
    pub(crate) lightlevel: i32,

    /// The leftmost horizontal screen column index bound for drawing.
    pub(crate) minx: i32,

    /// The rightmost horizontal screen column index bound for drawing.
    pub(crate) maxx: i32,
  
    /// Memory padding byte mimicking historical x-1 lookups.
    pub(crate) pad1: u8,

    /// Dynamic horizontal boundary array tracing top rendering margins across columns.
    pub(crate) top: [u8; SCREENWIDTH],

    /// Memory padding byte mimicking historical array bounds checks.
    pub(crate) pad2: u8,

    /// Memory padding byte mimicking historical array bounds checks.
    pub(crate) pad3: u8,

    /// Dynamic horizontal boundary array tracing bottom rendering margins across columns.
    pub(crate) bottom: [u8; SCREENWIDTH],

    /// Memory padding byte mimicking historical x+1 lookups.
    pub(crate) pad4: u8,
}