use std::io;

use io::Cursor;
use io::Read;
use io::Seek;

use io::BufWriter;
use io::Write;

use calamine::Reader;
use calamine::Sheets;

pub fn rdr2sheets<R, RS>(rdr: &R) -> Vec<String>
where
    R: Reader<RS>,
    RS: Read + Seek,
{
    rdr.sheet_names()
}

pub fn xbytes2sheet_names(xbytes: &[u8]) -> Result<Vec<String>, io::Error> {
    let cur = Cursor::new(xbytes);
    let sheets: Sheets<_> = calamine::open_workbook_auto_from_rs(cur).map_err(io::Error::other)?;
    Ok(rdr2sheets(&sheets))
}

pub fn reader2bytes2sheets2writer<R, W>(xrdr: R, limit: u64, mut swtr: W) -> Result<(), io::Error>
where
    R: Read,
    W: Write,
{
    let mut taken = xrdr.take(limit);
    let mut buf: Vec<u8> = vec![];
    taken.read_to_end(&mut buf)?;
    let sheet_names: Vec<String> = xbytes2sheet_names(&buf)?;
    for name in sheet_names {
        writeln!(&mut swtr, "{name}")?;
    }
    swtr.flush()
}

pub const INPUT_BYTES_LIIMT_DEFAULT: u64 = 1048576;

pub fn stdin2bytes2sheets2stdout(limit: u64) -> Result<(), io::Error> {
    let o = io::stdout();
    let mut ol = o.lock();
    reader2bytes2sheets2writer(io::stdin().lock(), limit, BufWriter::new(&mut ol))?;
    ol.flush()
}
