from typing import Union
from io import BytesIO
import pandas as pd


def read_part(filepath: str, start_line: int, end_line: int, verbose: bool = True) -> Union[None, bytes]:
    if verbose:
        print(f"Reading lines {start_line} to {end_line} from {filepath}")

    with open(filepath, 'rb') as f:
        byte_index  = 0
        byte_start  = None
        byte_end    = None

        line_number = 1
        while True:
            if line_number == start_line and byte_start is None:
                byte_start = byte_index
            
            if line_number == end_line and byte_end is None:
                byte_end = byte_index
                break

            byte = f.read(1)
            byte_index += 1
            if byte == b"\n":
                line_number += 1
            
            if byte == b"": # EOF
                if byte_start is None:
                    print(f"Error: start line {start_line} out of range {line_number}")
                    return None
                if byte_end is None:
                    byte_end = byte_index
                break

        assert(byte_start is not None and byte_end is not None)
                
        f.seek(byte_start)
        # print(f.read(byte_end - byte_start).decode('utf-8'))

        if verbose:
            print(f"Read {byte_end - byte_start} bytes")

        return f.read(byte_end - byte_start)


def read_csv_part(filepath: str, start_line: int, end_line: int, verbose: bool = True) -> Union[None, pd.DataFrame]:
    data = read_part(filepath, start_line, end_line)
    if data is None:
        return None
    
    if verbose:
        print("Parsing CSV...")
    res = pd.read_csv(BytesIO(data))
    if verbose:
        print("Done")
    return res.values


if __name__ == '__main__':
    # file_pth = 
