pub(crate) use self::image::ImageIntoIter;
use crate::{
    Grib2GpvUnpack,
    decoder::{
        DecodeError, Grib2SubmessageDecoder, jpeg2000::decoder::DecodeParams, simple::*,
        stream::FixedValueIterator,
    },
};

pub(crate) struct Jpeg2000<'d>(
    pub(crate) &'d Grib2SubmessageDecoder,
    pub(crate) &'d crate::def::grib2::template::Template5_40,
);

impl<'d> Grib2GpvUnpack for Jpeg2000<'d> {
    type Iter<'a>
        = SimplePackingDecoder<Jpeg2000Iter>
    where
        Self: 'a;

    fn iter<'a>(&'a self) -> Result<Self::Iter<'a>, DecodeError> {
        let Self(target, template) = self;
        super::orig_field_type_is_supported(template.orig_field_type)?;

        if template.simple.num_bits == 0 {
            // Tested with the World Aviation Forecast System (WAFS) GRIV files from the repo: https://aviationweather.gov/wifs/api.html
            // See #111 and #113.
            let decoder = SimplePackingDecoder::ZeroLength(FixedValueIterator::new(
                template.simple.zero_bit_reference_value(),
                target.num_encoded_points(),
            ));
            return Ok(decoder);
        };

        let jp2_unpacked = decode_j2k(target.sect7_payload())?;
        let decoder = NonZeroSimplePackingDecoder::new(jp2_unpacked, &template.simple);
        let decoder = SimplePackingDecoder::NonZeroLength(decoder);
        Ok(decoder)
    }
}

type Jpeg2000Iter = ImageIntoIter;

fn decode_j2k(bytes: &[u8]) -> Result<Jpeg2000Iter, DecodeError> {
    let stream = stream::Stream::from_bytes(bytes)?;
    let decoder = decoder::Decoder::new(stream)?;
    decoder.setup(DecodeParams::default())?;
    let image = decoder.read_header()?;
    decoder.decode(&image)?;

    image.try_into_iter()
}

mod decoder;
mod image;
mod stream;
