// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR MPL-2.0
// SPDX-FileCopyrightText: 2026 Gabriel Marcano <gabemarcano@yahoo.com>

use crate::error::Error;
use crate::metadata::Metadata;
use crate::metadata::MetadataRead;

use std::io::Read;
use std::io::Seek;

/// Represents a readable N64 cartridge.
pub struct Cart<T: Read + Seek> {
    /// Header metadata
    pub metadata: Metadata,
    /// Underlying IO object
    io: T,
}

impl<T: Read + Seek> Cart<T> {
    /// Creates a [`Cart`] by extracting the information from the given IO object, and takes
    /// ownership of it.
    ///
    /// # Errors
    ///
    /// See [`MetadataRead::read_n64_metadata`] for details.
    pub fn try_from(io: T) -> Result<Self, Error> {
        let mut io = io;
        Ok(Self {
            metadata: io.read_n64_metadata()?,
            io,
        })
    }

    /// Computes the checksum for the ROM, as found in the [`Metadata::check_code`] field.
    ///
    /// # Errors
    /// Returns [`Error::Io`] if there are any errors reading from the underlying IO object, and
    /// [`Error::Parse`] if it wasn't possible to determine the checksum (usually due to the IPL3
    /// portion of the ROM being scrambled).
    pub fn compute_checksum(&mut self) -> Result<u64, Error> {
        self.metadata.compute_checksum(&mut self.io)
    }
}
