from dom_utils import get_dom_elements, display_status, update_generate_button_text, update_time_inputs, update_calms_value, update_units_value
from input_utils import parse_input
from data_processing import load_csv, filter_dataframe 
from plot_utils import create_pollution_rose, clear_plot, download_data, download_table, download_plot
from event_handlers import attach_event_listeners
from js import console, FileReader, document
from pyodide.ffi import create_proxy
import traceback

# Fetch DOM elements
# problem -- using a global variable may not be ideal
# idea for refactoring -- use dependency injection to pass the elements to the functions that need them
elements = get_dom_elements()
df = None


# Check for missing elements
# Consider removing this. Is it really necessary? 
# could just do this in get_dom_elements and display a message if any elements are missing.
missing_elements = [name for name, el in elements.items() if el is None]
if missing_elements:
    display_status(elements["status_div"], f"Missing elements: {', '.join(missing_elements)}", level="error")
else:
    display_status(elements["status_div"], "Ready. Select a file and click Generate.", level="info")

# Event handlers
# using js for event handlers, consider using python @when decorator instead
def generate_button_clicked(event):
    """Handles the 'Generate' button click event."""
    # for debugging purposes, remove when not needed
    console.log("DEBUG: --- generate_button_clicked START ---")

    # Using global variable not recommended, consider refactoring
    global df 

    # check that a df is loaded. if not, display an error message and return
    if df is None:
        display_status(elements["status_div"], "No data loaded. Please upload a CSV first.", level="error")
        console.error("DEBUG: DataFrame is None")
        return

    try:
        # Parse user inputs
        params = parse_input(document)
        # Filter the DataFrame based on user inputs
        df_filtered, calms_freq = filter_dataframe(df, params)
        # Generate the pollution rose plot
        # lambda function to display status messages raised from the create_pollution_rose function
        # needed because the status_div is not in the scope of the create_pollution_rose function. Consider refactoring this
        create_pollution_rose(
            df_filtered, params, calms_freq,
            lambda msg, level="info": display_status(elements["status_div"], msg, level)
        )

        # Attach the filtered DataFrame to the download button
        download_button = elements["download_data_button"]
        download_button.df_filtered = df_filtered

    # reconsider how these are logged to the status div-- probably should not log the same thing to both
    except ValueError as ve:
        display_status(elements["status_div"], f"{ve}", level="error")
        console.error(f"DEBUG: generate_button_clicked ValueError: {ve}")
    except Exception as e:
        error_trace = traceback.format_exc()
        display_status(elements["status_div"], f"An unexpected error occurred: {e}", level="error")
        console.error(f"DEBUG: --- generate_button_clicked UNEXPECTED ERROR ---\n{e}\n{error_trace}\n--- End ERROR ---")
    console.log("DEBUG: --- generate_button_clicked END ---")


def on_file_selected(event):
    """Handles the file upload event."""
    console.log("DEBUG: File Upload Event Triggered")
    files = event.target.files
    generate_button = elements["generate_button"]

    if files.length == 0:
        display_status(elements["status_div"], "No file selected. Please upload a CSV file.", level="warning")
        generate_button.setAttribute("disabled", "true")  
        return

    # Check if the uploaded file is a CSV. 
    file = files.item(0)
    if not file.name.endswith('.csv'):
        display_status(elements["status_div"], "Invalid file type. Please upload a CSV file.", level="error")
        generate_button.setAttribute("disabled", "true")
        return

    # uses js FileReader to read the file content
    reader = FileReader.new()

    def on_file_read_complete(e):
        try:
            console.log("DEBUG: onload_handler triggered")
            csv_text = e.target.result
            global df
            df = load_csv(csv_text)

            update_time_inputs(df, elements)

            
            display_status(elements["status_div"], "File loaded successfully.", level="success")
            generate_button.removeAttribute("disabled")
        except Exception as ex:
            error_trace = traceback.format_exc()
            display_status(elements["status_div"], f"Error loading file: {ex}", level="error")
            console.error(f"DEBUG: File read error:\n{error_trace}")
            generate_button.setAttribute("disabled", "true")  # Disable the button

    reader.onload = create_proxy(on_file_read_complete)
    reader.readAsText(file)

def clear_plot_button_clicked(event):
    """Handles the 'Clear Plot' button click event."""
    clear_plot()
    # Hide the "Clear Plot" button after clearing plot
    elements["clear_plot_button"].classList.add("d-none")
    display_status(elements["status_div"], "Plots cleared.", level="info")
    elements["toggle_data_button"].classList.add("d-none")
    #FIXME: this is a temporary solution to hide the output data.  permanent solution would hide the output div completely
    elements["data_output_div"].innerHTML = ""
    elements["download_data_button"].classList.add("d-none")
    elements["download_plot_button"].classList.add("d-none")
    elements["download_table_button"].classList.add("d-none")

def on_rose_type_change(event):
    """Handles the change event for the Rose Type dropdown."""
    update_generate_button_text(event, elements["generate_button"])
    update_calms_value(event)
    update_units_value(event)

def on_collapse_hide(event):
    """Handles the collapse hide event to update the button text."""
    console.log("DEBUG: Collapse hide event triggered")
    toggle_button = document.getElementById("toggle-data-button")
    toggle_button.innerHTML = "Show Data used to generate plot"

def on_collapse_show(event):
    """Handles the collapse show event to update the button text."""
    console.log("DEBUG: Collapse show event triggered")
    toggle_button = document.getElementById("toggle-data-button")
    toggle_button.innerHTML = "Hide Data"

def on_download_data_button_clicked(event):
    """Handles the 'Download Data' button click event."""
    df_filtered = event.target.df_filtered
    if df_filtered is not None:
        download_data(df_filtered)
    else:
        display_status(elements["status_div"], "No filtered data available to download.", level="error")

def on_download_plot_button_clicked(event):
    """Handles the 'Download Plot' button click event."""
    img_base64 = event.target.img_base64
    if img_base64 is not None:
        download_plot(img_base64)
    else:
        console.error("No plot image available for download.")

def on_download_table_button_clicked(event):
    """Handles the 'Download Table' button click event."""
    df = event.target.output_table
    if df is not None:
        download_table(df)
    else:
        console.error("No table data available for download.")
# Attach event listeners
# FIXME: need to rethink this. Too many parameters being passed at once. Could probably just attach event handlers individually.
attach_event_listeners(elements, generate_button_clicked, on_file_selected, clear_plot_button_clicked, on_rose_type_change, on_collapse_hide, on_collapse_show, on_download_data_button_clicked,
                       on_download_plot_button_clicked, on_download_table_button_clicked) 