// SPDX-FileCopyrightText: 2023 CELESTIFYX Team
// SPDX-License-Identifier: GPL-3.0-or-later

use anyhow::Result;

use std::{
    env,
    io::Cursor
};

use base64::{
    Engine,
    engine
};

use image::{
    DynamicImage,
    imageops::FilterType
};

use rustix::termios::{
    tcgetwinsize,
    Winsize
};

use super::ImageBackend;
use crate::image::config::DisplayConfig;

pub(super) struct ITermBackend;

impl ITermBackend {
    pub(super) fn supported() -> bool {
        env::var("TERM_PROGRAM").unwrap_or_default() == "iTerm.app"
    }
}

impl ImageBackend for ITermBackend {
    fn add_image(&self, config: &DisplayConfig, image: &DynamicImage) -> Result<String> {
        let tty_size: Winsize = tcgetwinsize(std::io::stdin())?;
        let mut bytes: Vec<u8> = Vec::new();

        let height_ratio: f64 = f64::from(tty_size.ws_row) / f64::from(tty_size.ws_ypixel);
        let image_rows:   f64 = height_ratio * f64::from(image.height());

        let image: DynamicImage = image.resize(u32::MAX, (config.lines.len() as f64 / height_ratio) as u32, FilterType::Lanczos3);
        image.write_to(&mut Cursor::new(&mut bytes), image::ImageFormat::Png)?;

        let encoded_image: String = engine::general_purpose::STANDARD.encode(bytes);
        let mut image_data: Vec<u8> = Vec::<u8>::new();

        (&mut image_data).extend(b"\x1B]1337;File=inline=1:");
        (&mut image_data).extend(encoded_image.bytes());
        (&mut image_data).extend(b"\x07");
        (&mut image_data).extend(format!("\x1B[{}A", image_rows as u32 - 1).as_bytes()); // move cursor to start of image

        let mut i: usize = 0;

        for line in &config.lines {
            (&mut image_data).extend(format!("\x1B[s{}{}\x1B[u\x1B[1B", " ".repeat(config.margin), line).as_bytes());
            i += 1;
        }

        (&mut image_data).extend(format!("\n\x1B[{}B", config.lines.len().max(image_rows as usize) - i).as_bytes()); // move cursor to end of image
        Ok(String::from_utf8(image_data)?)
    }
}
