use std::{path::Path, fs::File, io::{self, BufRead, Read}};
use crate::game::Game;

/// An error when reading the file
#[derive(Debug)]
pub enum ReaderError {
    FileAccessError,
    ParseError,
}


/// Read the file at a given path. If all goes well, will return `Ok(game)`, with a game
/// initialised with that pattern. Can return errors for either file access or failed parsing. 
pub fn read_game_at_path(path: &str) -> Result<Game, ReaderError> {
    let path = Path::new(path);
    let file = open_file(path)?;
    read_game(file)
}

/// Read from any `impl Read`. If all goes well, will return `Ok<Game>` with a game 
/// initialised with that pattern. Can return errors for failed parsing. 
pub fn read_game(file: impl Read) -> Result<Game, ReaderError> {
    let lines = io::BufReader::new(file).lines();
    let mut game = Game::new();
    let mut x_index = 0;
    for line in lines {
        if let Ok(ip) = line {
            // Comment/metadata
            if ip.starts_with("!") || ip.starts_with("#") {continue}
            x_index += 1;
            for (cell, y_index) in ip.chars().zip(0..) {
                match cell {
                    // Live cell
                    '*' | 'O' => {game.flip_state((y_index, x_index));},
                    // Dead cell
                    '.' | ' ' => continue,
                    // Invalid character
                    _ => {return Err(ReaderError::ParseError);},
                }
                /*if cell == '*' || cell == 'O' {
                    // Live cell
                    game.flip_state((y_index, x_index));
                } else if cell == '.' || cell == ' ' {
                    // Dead cell
                    continue
                } else {
                    // Invalid character
                    return Err(ReaderError::ParseError);
                }*/
            }
        }
    }
    Ok(game)
}


fn open_file(path: &Path) -> Result<File, ReaderError> {
    match File::open(path) {
        Ok(file) => Ok(file),
        Err(_) => Err(ReaderError::FileAccessError),
    }
}
