eorst 1.0.1

Earth Observation and Remote Sensing Toolkit - library for raster processing pipelines
use crate::core_types::RasterType;
use crate::data_sources::DateType;
use crate::rasterdataset::RasterDataset;
use colored::*;
use std::any::type_name;

impl std::fmt::Display for DateType {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
        let str = match self {
            DateType::Date(date) => {
                format!("{}", date.format("%Y-%m-%d %H:%M:%S"))
            }
            DateType::Index(index) => format!("{}", index),
        };
        write!(fmt, "{}", str)
        //writeln!(fmt, "")
    }
}

impl<T> std::fmt::Display for RasterDataset<T>
where
    T: RasterType,
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
        writeln!(fmt, "{}", "Summary".bold().underline())?;

        // -------------------------
        // Quick multi-line summary
        // -------------------------
        writeln!(
            fmt,
            "{:<20} : {}x{} pixels",
            "Size".cyan(),
            self.metadata.shape.rows,
            self.metadata.shape.cols
        )?;
        writeln!(
            fmt,
            "{:<20} : {} layers",
            "Layers".cyan(),
            self.metadata.shape.layers
        )?;
        writeln!(
            fmt,
            "{:<20} : {} time(s)",
            "Time steps".cyan(),
            self.metadata.shape.times
        )?;
        writeln!(
            fmt,
            "{:<20} : {} block(s)",
            "Blocks".cyan(),
            self.blocks.len()
        )?;
        writeln!(fmt, "{:<20} : {}", "Data type".cyan(), type_name::<T>())?;
        writeln!(
            fmt,
            "{:<20} : {}",
            "Null Value".cyan(),
            self.metadata.na_value
        )?;

        writeln!(
            fmt,
            "{:<20} : EPSG:{}",
            "EPSG code".cyan(),
            self.metadata.epsg_code
        )?;

        writeln!(fmt)?; // empty line before detailed table

        // -------------------------
        // Layer indices (summarized)
        // -------------------------
        let layer_indices_str = if self.metadata.layer_indices.len() > 5 {
            format!(
                "{} ... (+{} more)",
                self.metadata.layer_indices[..5].join(", "),
                self.metadata.layer_indices.len() - 5
            )
        } else {
            self.metadata.layer_indices.join(", ")
        };

        // -------------------------
        // Time indices (summarized)
        // -------------------------
        let time_indices_str = if self.metadata.date_indices.len() > 5 {
            self.metadata.date_indices[..5]
                .iter()
                .map(|val| match val {
                    DateType::Date(date) => format!("{}", date.format("%Y-%m-%d %H:%M:%S")),
                    DateType::Index(idx) => idx.to_string(),
                })
                .collect::<Vec<_>>()
                .join(", ")
                + &format!(" ... (+{} more)", self.metadata.date_indices.len() - 5)
        } else {
            self.metadata
                .date_indices
                .iter()
                .map(|val| match val {
                    DateType::Date(date) => format!("{}", date.format("%Y-%m-%d %H:%M:%S")),
                    DateType::Index(idx) => idx.to_string(),
                })
                .collect::<Vec<_>>()
                .join(", ")
        };

        // -------------------------
        // Detailed attribute table
        // -------------------------
        writeln!(fmt, "{}", "Details".bold().underline())?;

        let table = vec![
            (
                "Dataset shape",
                format!(
                    "times: {}, layers: {}, rows: {}, cols: {}",
                    self.metadata.shape.times,
                    self.metadata.shape.layers,
                    self.metadata.shape.rows,
                    self.metadata.shape.cols
                ),
            ),
            ("Layer indices", layer_indices_str),
            ("Time indices", time_indices_str),
            (
                "Block size",
                format!(
                    "{}x{}",
                    self.metadata.block_size.rows, self.metadata.block_size.cols
                ),
            ),
            ("Number of blocks", self.blocks.len().to_string()),
            (
                "GeoTransform",
                format!(
                    "{:>2}, {:>2}, {:>2}, {:>2}, {:>2}, {:>2}",
                    self.metadata.geo_transform.x_res,
                    self.metadata.geo_transform.x_rot,
                    self.metadata.geo_transform.x_ul,
                    self.metadata.geo_transform.y_rot,
                    self.metadata.geo_transform.y_res,
                    self.metadata.geo_transform.y_ul
                ),
            ),
        ];

        for (key, value) in table {
            writeln!(fmt, "{:<20} : {}", key.bold(), value)?;
        }

        Ok(())
    }
}