import marimo

__generated_with = "0.10.16"
app = marimo.App(width="medium")


@app.cell(hide_code=True)
def title():
    import marimo as mo
    notebook_name = 'run_perfspec.py'

    from lib_perfspec import perfspec_vars
    (_,_defs) = perfspec_vars.run()
    perfspec = _defs['perfspec']

    from lib_perfspec import perfspec_header
    (_,_defs) = perfspec_header.run()
    lib_header = _defs['header']
    lib_intro = _defs['intro']

    mo.md(
        f"""
        {lib_header(notebook_name)}
        ### Use **{perfspec['app']['train_mode']}** trained model
        """
    )
    return (
        lib_header,
        lib_intro,
        mo,
        notebook_name,
        perfspec,
        perfspec_header,
        perfspec_vars,
    )


@app.cell
def imports():
    from pathlib import Path
    return (Path,)


@app.cell(hide_code=True)
def intro_load(Path, lib_intro, mo, notebook_name, perfspec):
    verbose = perfspec['settings']['verbose']
    perfspec['vars'] = {}

    from lib_perfspec import perfspec_args
    (_,_defs) = perfspec_args.run()

    if not Path(perfspec['defaults']['models_dirpath']).exists(): 
       exit(f"Trained models dir path not found: {perfspec['defaults']['models_dirpath']}")  

    if not Path(perfspec['defaults']['checkpoints_dirpath']).exists(): 
       exit(f"Trained checkpoints models dir path not found: {perfspec['defaults']['checkpoints_dirpath']}")  

    if not Path(perfspec['defaults']['data_dirpath']).exists(): 
       exit(f"data dir path not found: {perfspec['defaults']['data_dirpath']}")  

    verbose=perfspec['settings'].get('verbose')

    from lib_perfspec import perfspec_load_actions
    (_,_defs) = perfspec_load_actions.run()
    lib_load_actions = _defs['load_actions']

    from lib_perfspec import perfspec_input_sequence
    (_,_defs) = perfspec_input_sequence.run()
    lib_get_input_sequence = _defs['get_input_sequence']

    from lib_perfspec import perfspec_predict
    _, _defs = perfspec_predict.run()
    lib_predict_action = _defs['predict_action']

    perfspec['vars']['model'] = None
    perfspec['vars']['history'] = None

    (perfspec['vars']['actions'], 
    perfspec['vars']['unique_actions'], 
    perfspec['vars']['label_encoder'], 
    perfspec['vars']['encoded_actions']
    ) = lib_load_actions(
        actions_path=perfspec['settings'].get('actions_filepath'),
        verbose=None
    )

    perfspec['vars']['input_sequence'] = lib_get_input_sequence(
        input_str=perfspec['settings']['input_str'], 
        unique_actions=perfspec['vars']['unique_actions']
    )

    from train_perfspec import perfspec_load_model_from_path
    (_,_defs) = perfspec_load_model_from_path.run()
    lib_load_model_from_path = _defs['load_model_from_path']

    mo.md(
        f"""
        {lib_intro(notebook_name)}

        """
    )
    return (
        lib_get_input_sequence,
        lib_load_actions,
        lib_load_model_from_path,
        lib_predict_action,
        perfspec_args,
        perfspec_input_sequence,
        perfspec_load_actions,
        perfspec_load_model_from_path,
        perfspec_predict,
        verbose,
    )


@app.cell(hide_code=True)
def settings(mo, notebook_name):
    from lib_perfspec import perfspec_out_settings
    (_,_defs) = perfspec_out_settings.run()
    out_settings = _defs['out_settings']

    mo.md(out_settings(notebook_name))
    return out_settings, perfspec_out_settings


@app.cell(hide_code=True)
def command_line(mo, notebook_name):
    from lib_perfspec import perfspec_cli_ops
    (_,_defs) = perfspec_cli_ops.run()
    out_cli_ops = _defs['out_cli_ops']
    mo.accordion({ 
        "Mostrar command Line options ": out_cli_ops(notebook_name) 
    })
    return out_cli_ops, perfspec_cli_ops


@app.cell(hide_code=True)
def load_trained_model(lib_load_model_from_path, mo, perfspec):
    def load_trained_model():
        if perfspec['vars']['model'] == None:
           _verbose = perfspec['settings']['verbose'] # if mo.running_in_notebook() else perfspec['settings']['verbose']
           perfspec['vars']['model'] = lib_load_model_from_path(perfspec,_verbose)       
        if perfspec['vars']['model'] == None:
            print ("No model loaded !")

    mo.md(
        r"""
        ## Load trained model
        """
    )
    return (load_trained_model,)


@app.cell(hide_code=True)
def model_summary(load_trained_model, mo, perfspec):
    def model_sumary():
        load_trained_model()
        if perfspec['vars']['model'] != None:
            perfspec['vars']['model'].summary()

    if perfspec['settings']['verbose'] is not None or mo.running_in_notebook():
        model_sumary()
    mo.md(
        r"""
        ## Model Summary
        """
    )
    return (model_sumary,)


@app.cell(hide_code=True)
def perfspec_def_predict_input(
    input_multiselect,
    lib_get_input_sequence,
    lib_predict_action,
    load_trained_model,
    mo,
    model_sumary,
    perfspec,
    run_evaluate,
):
    def predict_input(pred_input, verbose):
        #verbose = "1" if mo.running_in_notebook() else perfspec['settings']['verbose']
        if type(pred_input) == str and pred_input != '':
           input_sequence = lib_get_input_sequence(pred_input,perfspec['vars']['unique_actions'])
        elif type(pred_input) != str and len(pred_input) > 0:
           input_sequence = pred_input
        elif mo.running_in_notebook() and len(input_multiselect.value) > 0:
            input_sequence= input_multiselect.value
        elif perfspec['defaults']['pred_input'] != '':
            input_sequence = lib_get_input_sequence(perfspec['defaults']['pred_input'],perfspec['vars']['unique_actions'])
        else:
            print (f"No input found ! {input_sequence}")
            return 
        if len(input_sequence) > 0:
            if verbose == "x":
               model_sumary()
               run_evaluate()
               print ("\nPrediction")
            if perfspec['vars']['model'] == None:
               load_trained_model()
            if perfspec['vars']['model'] != None:
                (encoded_input,predicted_probabilities) = lib_predict_action(
                       perfspec['vars']['model'],
                       perfspec['settings']['sequence_length'],
                       input_sequence,
                       perfspec['vars']['label_encoder'],
                       verbose 
                )
                return (encoded_input,predicted_probabilities)
            else:
                print (f"No Model found to predict {input_sequence}")
        return (None,None)
    return (predict_input,)


@app.cell(hide_code=True)
def multiselect_def(mo, perfspec):
    input_multiselect = mo.ui.multiselect(
        options=perfspec['vars']['unique_actions'],
        full_width=True,
        max_selections=perfspec['settings']['sequence_length'],
    )
    return (input_multiselect,)


@app.cell(hide_code=True)
def perfspec_def_show_value_selector(
    input_multiselect,
    mo,
    perfspec,
    predict_input,
):
    def show_value():
        if len(input_multiselect.value) > 0:    
            if len(input_multiselect.value) > perfspec['settings']['sequence_length']:    
                return ""
            (_,prediction) = predict_input(input_multiselect.value, None)
            table_info = mo.md(f"""
                | desc. | value | % |
                | ---- | --- | --- |
                | input | {",".join(input_multiselect.value)}| |
                | prediction | {prediction['action'][0]} |{prediction['max_value']}|
                """)
            return mo.md(f"{mo.vstack(justify='center',items=[mo.md("<h3 style='margin-left: 7em'>Actions</h3>"),table_info])}")
        else: 
            return ""
    return (show_value,)


@app.cell(hide_code=True)
def title_run_prediction(mo, perfspec):
    mo.md(
        f"""
        ## Run Model Prediction

        Use **{perfspec['vars']['input_sequence']}** with trained model <u>created</u> or <u>loaded</u>
        <br>from {perfspec['settings']['model_filepath']}

        input value can be changed in **command-line** with **--input** `value` argument<br>
        with **--verbose**  option more info is show in **command-line** mode
        """
    )
    return


@app.cell(hide_code=True)
def _(mo, perfspec, predict_input):
    def run_prediction():
        _verbose = perfspec["settings"]["verbose"]
        if perfspec["settings"]["verbose"] is None and mo.running_in_notebook():
            _verbose=1
        predict_input("", _verbose)

    run_prediction()

    mo.md(
        """
        ### Test default prediction
        """
    )
    return (run_prediction,)


@app.cell(hide_code=True)
def main(mo):
    mo.md("""<a id='main' />""")
    return


@app.cell(hide_code=True)
def perfspec_predictions_selector(
    input_multiselect,
    mo,
    perfspec,
    show_value,
):
    def show_selector():
        if mo.running_in_notebook():
            if perfspec['settings']['sequence_length'] > 1:
                seq_msg = f"<br> <small>For better `prediction` use at least **{perfspec['settings']['sequence_length']}** options"
            else:
                seq_msg = ""
            return f"""
                {mo.hstack(widths="equal",gap=3,wrap=True,items=[
                    mo.vstack(items=[mo.md("""
                        ## Predictions
                        Select values to get prediction
                        """),input_multiselect]),
                    show_value()]
                )}
                > <small>if notebook **autorun** is not set, use <u>click on cell to run</u></small>
                {seq_msg}
                """
        else:
            return ""
    mo.md(show_selector())
    return (show_selector,)


if __name__ == "__main__":
    app.run()
