# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/00_main.ipynb (unless otherwise specified).

__all__ = ['CACHE_FOLDER', 'custom_theme', 'console', 'read_meta', 'process_bin']

# Cell
from datetime import datetime
from typing import *
import os
import logging
from fastcore.xtras import Path
from fastcore.script import call_parse, Param, store_true
import numpy as np
import pandas as pd
from rich.progress import Progress
from rich.console import Console
from rich.theme import Theme
from rich.logging import RichHandler
from rfpy.utils import *
from rfpy.constants import SPECTRAL_BLOCKS
from rfpy.parser import *
CACHE_FOLDER = Path(r"C:\Users\rsilva\Downloads\saida")
if not CACHE_FOLDER.exists():
    CACHE_FOLDER = Path.cwd() / 'cache'
    CACHE_FOLDER.mkdir(exist_ok=True, parents=True)

# Cell
custom_theme = Theme({"info": "dim cyan", "warning": "magenta", "danger": "bold red"})
console = Console(theme=custom_theme)

# Cell
def read_meta(filename):
    ext = filename.suffix
    if ext == ".csv":
        df = pd.read_csv(filename)
    elif ext == ".xlsx":
        df = pd.read_excel(filename, engine="openpyxl")
    elif ext == ".fth":
        df = pd.read_feather(filename)
        if "wallclock_datetime" in df.columns:
            df.set_index("wallclock_datetime", inplace=True)
    else:
        raise ValueError(f"Extension {ext} not implemented")
    return df

# Cell
@call_parse
def process_bin(
    entrada: Param("Arquivo .bin ou Diretório contendo arquivos .bin", str),
    saida: Param("Diretório para salvar os arquivos de saída", str),
    recursivo: Param("Buscar arquivos de maneira recursiva?", store_true) = False,
    pastas: Param("Limitar a busca às pastas", Iterable[str]) = None,
    levels: Param("Extrair e Salvar os níveis de Espectro?", store_true) = False,
    meta_ext: Param("Extensão do arquivo de metadados", str) = ".fth",
    levels_ext: Param("Extensão do arquivo de níveis", str) = ".fth",
    substituir: Param(
        "Reprocessar e substituir arquivos existentes?", store_true) = False,
    dtype: Param("Tipo de Dado ao salvar o arquivo de nível", str) = 'float16'
):
    entrada = Path(entrada)
    if entrada.is_file():
        lista_bins = [entrada]
    else:
        lista_bins = get_files(
            entrada, extensions=[".bin"], recurse=recursivo, folders=pastas
        )
    parsed_bins = {}
    meta_path = Path(f"{saida}/meta")
    levels_path = Path(f"{saida}/levels")
    meta_path.mkdir(exist_ok=True, parents=True)
    levels_path.mkdir(exist_ok=True, parents=True)
    log_meta = Path(f"{saida}/log_meta.txt")
    log_levels = Path(f"{saida}/log_levels.txt")
    if substituir:
        done_meta = set()
        done_levels = set()
    else:

        done_meta = (
            set(log_meta.read_text().split("\n")) if log_meta.exists() else set()
        )
        done_levels = (
            set(log_levels.read_text().split("\n")) if log_levels.exists() else set()
        )

    console.rule("Lista de Arquivos a serem processados", style="bold red")
    console.print(
        [f.name for f in lista_bins],
        style="bold white",
        overflow="fold",
        justify="left",
    )
    if not lista_bins:
        console.print(":sleeping: Nenhum arquivo .bin a processar :zzz:")
        return

    if not levels:
        lista_bins = [f for f in lista_bins if f.name not in done_meta]
    else:
        lista_bins = [f for f in lista_bins if f.name not in done_levels]

    if not lista_bins:
        console.print(":sleeping: Nenhum arquivo novo a processar :zzz:")
        console.print(
            ":point_up: use --substituir no terminal ou substituir=True na chamada caso queira reprocessar os bins e sobrepôr os arquivos existentes :wink:"
        )
        return

    try:

        with Progress(transient=True, auto_refresh=False) as progress:
            bins = progress.track(
                lista_bins,
                total=len(lista_bins),
                description="[green]Processando Blocos Binários",
            )

            for file in bins:
                progress.console.print(f"[cyan]Processando Blocos de: [red]{file.name}")
                parsed_bins[file.name] = parse_bin(file)
                progress.refresh()

            lista_meta = [(k,v) for k,v in parsed_bins.items() if k not in done_meta]

            if lista_meta:
                blocks = progress.track(
                    lista_meta, total=len(lista_meta), description="[cyan]Exportando Metadados"
                )
                for file, block in blocks:
                    progress.console.print(
                        f"[cyan]Extraindo Metadados de: [red]{file}"
                    )
                    export_meta(
                        file, block, meta_path, ext=meta_ext
                    )
                    done_meta.add(file)
                    progress.refresh()
            if levels:
                lista_levels = lista_meta = [(k,v) for k,v in parsed_bins.items() if k not in done_levels]
                if lista_levels:
                    bins = progress.track(
                        lista_levels,
                        total=len(lista_levels),
                        description="[grey]Exportando Dados de Espectro",
                    )
                    for file, block_obj in bins:
                        progress.console.print(
                            f"[grey]Extraindo Espectro de: [red]{file}"
                        )
                        meta_index = []
                        blocks = block_obj["blocks"]
                        for (tipo, tid) in blocks.keys():
                            if tipo not in SPECTRAL_BLOCKS:
                                continue
                            meta_file = Path(
                                f"{meta_path}/{file}-B_{tipo}_TId_{tid}{meta_ext}"
                            )
                            if not meta_file.exists():
                                export_meta(
                                    file,
                                    block_obj,
                                    meta_path,
                                    ext=meta_ext,
                                )
                                done_meta.add(file)
                            meta_df = read_meta(meta_file)
                            meta_index.append(meta_df.index.tolist())
                        export_level(
                            file,
                            block_obj,
                            levels_path,
                            ext=levels_ext,
                            index=meta_index,
                            dtype=dtype
                        )
                        done_levels.add(file)
                        progress.refresh()
        console.print("kbô :satisfied:")
    finally:
        log_meta.write_text("\n".join(sorted(list(done_meta))))
        log_levels.write_text("\n".join(sorted(list(done_levels))))