use crate::{
    CodingUnitContext, CodingUnitKind, EnumMappings, Frame, FrameError, PartitionContext, Plane, PlaneType, Spatial,
    SuperblockContext, SuperblockLocator, SymbolContext, TransformUnitContext,
};

pub enum ProtoEnumMapping {
    TransformType,
    EntropyCodingMode,
    InterpolationFilter,
    PredictionMode,
    UvPredictionMode,
    MotionMode,
    TransformSize,
    BlockSize,
    PartitionType,
    FrameType,
    TipMode,
    MotionVectorPrecision,
}

impl Frame {
    pub fn iter_coding_units(&self, kind: CodingUnitKind) -> impl Iterator<Item = CodingUnitContext> + '_ {
        self.iter_superblocks().flat_map(move |ctx| ctx.iter_coding_units(kind))
    }

    /// Whether this frame has separate luma and chroma partition trees (i.e. semi-decoupled partitioning - SDP).
    ///
    /// This is stored at the superblock level, but each superblock is assumed to have the same SDP setting.
    pub fn has_separate_chroma_partition_tree(&self) -> bool {
        if let Some(sb) = self.superblocks.first() {
            sb.has_separate_chroma_partition_tree
        } else {
            false
        }
    }

    pub fn coding_unit_kind(&self, plane_type: PlaneType) -> CodingUnitKind {
        match plane_type {
            PlaneType::Rgb => CodingUnitKind::Shared,
            PlaneType::Planar(Plane::Y) => {
                if self.has_separate_chroma_partition_tree() {
                    CodingUnitKind::LumaOnly
                } else {
                    CodingUnitKind::Shared
                }
            }
            PlaneType::Planar(Plane::U | Plane::V) => {
                if self.has_separate_chroma_partition_tree() {
                    CodingUnitKind::ChromaOnly
                } else {
                    CodingUnitKind::Shared
                }
            }
        }
    }

    pub fn iter_coding_unit_rects(&self, kind: CodingUnitKind) -> impl Iterator<Item = emath::Rect> + '_ {
        self.iter_coding_units(kind).map(|ctx| ctx.coding_unit.rect())
    }

    pub fn iter_transform_units(&self, plane: Plane) -> impl Iterator<Item = TransformUnitContext> {
        let kind = self.coding_unit_kind(PlaneType::Planar(plane));
        self.iter_coding_units(kind)
            .flat_map(move |ctx| ctx.iter_transform_units(plane))
    }

    pub fn iter_transform_rects(&self, plane: Plane) -> impl Iterator<Item = emath::Rect> + '_ {
        self.iter_transform_units(plane).map(|ctx| ctx.transform_unit.rect())
    }

    pub fn iter_superblocks(&self) -> impl Iterator<Item = SuperblockContext> {
        self.superblocks
            .iter()
            .enumerate()
            .map(|(i, superblock)| SuperblockContext {
                superblock,
                frame: self,
                locator: SuperblockLocator::new(i),
            })
    }

    pub fn iter_partitions(&self, kind: CodingUnitKind) -> impl Iterator<Item = PartitionContext> {
        self.iter_superblocks()
            .flat_map(move |superblock_context| superblock_context.iter_partitions(kind))
    }

    fn get_enum_mappings(&self) -> Result<&EnumMappings, FrameError> {
        self.enum_mappings
            .as_ref()
            .ok_or(FrameError::BadFrame("Missing enum mappings.".into()))
    }
    pub fn enum_lookup(&self, enum_type: ProtoEnumMapping, value: i32) -> Result<String, FrameError> {
        use FrameError::*;
        let enum_mappings = self.get_enum_mappings()?;
        match enum_type {
            ProtoEnumMapping::TransformType => enum_mappings
                .transform_type_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing transform type value: {value}"))),
            ProtoEnumMapping::EntropyCodingMode => enum_mappings
                .entropy_coding_mode_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing entropy coding mode value: {value}"))),
            ProtoEnumMapping::InterpolationFilter => enum_mappings
                .interpolation_filter_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing interpolation filter value: {value}"))),
            ProtoEnumMapping::PredictionMode => enum_mappings
                .prediction_mode_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing prediction mode value: {value}"))),
            ProtoEnumMapping::UvPredictionMode => enum_mappings
                .uv_prediction_mode_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing UV prediction mode value: {value}"))),
            ProtoEnumMapping::MotionMode => enum_mappings
                .motion_mode_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing motion mode value: {value}"))),
            ProtoEnumMapping::TransformSize => enum_mappings
                .transform_size_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing transform size value: {value}"))),
            ProtoEnumMapping::BlockSize => enum_mappings
                .block_size_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing block size value: {value}"))),
            ProtoEnumMapping::PartitionType => enum_mappings
                .partition_type_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing partition type value: {value}"))),
            ProtoEnumMapping::FrameType => enum_mappings
                .frame_type_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing frame type value: {value}"))),
            ProtoEnumMapping::TipMode => enum_mappings
                .tip_mode_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing TIP mode value: {value}"))),
            ProtoEnumMapping::MotionVectorPrecision => enum_mappings
                .motion_vector_precision_mapping
                .get(&value)
                .ok_or(BadFrame(format!("Missing MV precision value: {value}"))),
        }
        .cloned()
    }

    pub fn iter_superblock_rects(&self) -> impl Iterator<Item = emath::Rect> + '_ {
        self.iter_superblocks()
            .map(|superblock_context| superblock_context.superblock.rect())
    }

    pub fn iter_symbols(&self) -> impl Iterator<Item = SymbolContext> {
        self.iter_superblocks()
            .flat_map(move |superblock_context| superblock_context.iter_symbols(None))
    }

    pub fn bit_depth(&self) -> u8 {
        self.frame_params
            .as_ref()
            .map_or(0, |frame_params| frame_params.bit_depth as u8)
    }

    pub fn decode_index(&self) -> usize {
        self.frame_params
            .as_ref()
            .map_or(0, |frame_params| frame_params.decode_index as usize)
    }

    pub fn display_index(&self) -> usize {
        self.frame_params
            .as_ref()
            .map_or(0, |frame_params| frame_params.display_index as usize)
    }

    pub fn frame_type_name(&self) -> String {
        if let Some(frame_params) = self.frame_params.as_ref() {
            let frame_type = frame_params.frame_type;
            if let Ok(name) = self.enum_lookup(ProtoEnumMapping::FrameType, frame_type) {
                return name;
            }
        }
        "UNKNOWN".into()
    }

    pub fn tip_mode_name(&self) -> String {
        if let Some(tip_frame_params) = self.tip_frame_params.as_ref() {
            let tip_mode = tip_frame_params.tip_mode;
            if let Ok(name) = self.enum_lookup(ProtoEnumMapping::TipMode, tip_mode) {
                return name;
            }
        }
        "UNKNOWN".into()
    }
}
