use std::env;
use std::fs::File;
use std::io::{self, BufRead, BufReader};

fn main() -> io::Result<()> {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Usage: {} start-end [count] [file...]", args[0]);
        std::process::exit(1);
    }

    let range = &args[1];
    let (start, mut end) = if let Some(dash_pos) = range.find('-') {
        (range[..dash_pos].parse().unwrap(), range[dash_pos + 1..].parse().unwrap())
    } else {
        (range.parse().unwrap(), 0)
    };

    let mut count = 1;
    let mut files_start = 2;

    if end == 0 {
        if args.len() > 2 {
            if let Ok(c) = args[2].parse::<usize>() {
                count = c;
                files_start = 3;
            }
        }
        end = start + count - 1;
    }

    if args.len() > files_start {
        for filename in &args[files_start..] {
            let file = File::open(filename)?;
            let reader = BufReader::new(file);
            process_lines(reader, start, end)?;
        }
    } else {
        // No files provided, read from stdin
        let stdin = io::stdin();
        let reader = stdin.lock();
        process_lines(reader, start, end)?;
    }

    Ok(())
}

fn process_lines<R: BufRead>(reader: R, start: usize, end: usize) -> io::Result<()> {
    reader.lines()
          .enumerate()
          .filter_map(|(i, line)| if i + 1 >= start && i + 1 <= end { line.ok() } else { None })
          .for_each(|line| println!("{}", line));

    Ok(())
}
