use num_derive::FromPrimitive;
use crate::api::{Opaque, T35};
use crate::context::SB_SIZE;
use crate::mc::SUBPEL_FILTER_SIZE;
use crate::util::*;
use crate::tiling::*;
mod plane;
pub use plane::*;
const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE;
const LUMA_PADDING: usize = SB_SIZE + FRAME_MARGIN;
#[derive(Debug, PartialEq, Eq, Clone, Copy, FromPrimitive, Default)]
#[repr(C)]
pub enum FrameTypeOverride {
  #[default]
  No,
  Key,
}
#[derive(Debug, Default)]
pub struct FrameParameters {
  pub frame_type_override: FrameTypeOverride,
  pub opaque: Option<Opaque>,
  pub t35_metadata: Box<[T35]>,
}
pub use v_frame::frame::Frame;
pub(crate) trait FrameAlloc {
  fn new(width: usize, height: usize, chroma_sampling: ChromaSampling)
    -> Self;
}
impl<T: Pixel> FrameAlloc for Frame<T> {
  fn new(
    width: usize, height: usize, chroma_sampling: ChromaSampling,
  ) -> Self {
    v_frame::frame::Frame::new_with_padding(
      width,
      height,
      chroma_sampling,
      LUMA_PADDING,
    )
  }
}
pub(crate) trait FramePad {
  fn pad(&mut self, w: usize, h: usize, planes: usize);
}
impl<T: Pixel> FramePad for Frame<T> {
  fn pad(&mut self, w: usize, h: usize, planes: usize) {
    for pli in 0..planes {
      self.planes[pli].pad(w, h);
    }
  }
}
pub(crate) trait AsTile<T: Pixel> {
  fn as_tile(&self) -> Tile<'_, T>;
  fn as_tile_mut(&mut self) -> TileMut<'_, T>;
}
impl<T: Pixel> AsTile<T> for Frame<T> {
  #[inline(always)]
  fn as_tile(&self) -> Tile<'_, T> {
    let PlaneConfig { width, height, .. } = self.planes[0].cfg;
    Tile::new(self, TileRect { x: 0, y: 0, width, height })
  }
  #[inline(always)]
  fn as_tile_mut(&mut self) -> TileMut<'_, T> {
    let PlaneConfig { width, height, .. } = self.planes[0].cfg;
    TileMut::new(self, TileRect { x: 0, y: 0, width, height })
  }
}