#!/usr/bin/env python3

"""
Standardized Math Operation Node:
  - Performs mathematical operations (+, -, *, /, avg) on two inputs.
  - Outputs the computed result.
  - Uses a global update timer for processing (defined in borealis.py).
  - Ensures it always has a "value" property that the Comparison Node can read.
"""

from OdenGraphQt import BaseNode
from Qt import QtCore

class MathOperationNode(BaseNode):
    __identifier__ = 'bunny-lab.io.math_node'
    NODE_NAME = 'Math Operation'

    def __init__(self):
        super(MathOperationNode, self).__init__()
        self.add_input('A')
        self.add_input('B')
        self.add_output('Result')
        
        # Drop-down to choose which operation we do:
        self.add_combo_menu('operator', 'Operator', items=[
            'Add', 'Subtract', 'Multiply', 'Divide', 'Average'
        ])

        # A text field for showing the result to the user:
        self.add_text_input('calc_result', 'Result', text='0')

        # IMPORTANT: define a "value" property that the Comparison Node can read
        # We do not necessarily need a text input for it, but adding it ensures
        # it becomes an official property recognized by OdenGraphQt.
        self.add_text_input('value', 'Internal Value', text='0')

        # Keep a Python-side float of the current computed result:
        self.value = 0

        # Give the node a nice name:
        self.set_name("Math Operation")

        # Removed self-contained timer; global timer calls process_input().

    def process_input(self):
        # Attempt to read "value" from both inputs:
        input_a = self.input(0)
        input_b = self.input(1)
        a_raw = input_a.connected_ports()[0].node().get_property('value') if input_a.connected_ports() else "0"
        b_raw = input_b.connected_ports()[0].node().get_property('value') if input_b.connected_ports() else "0"

        try:
            a_val = float(a_raw)
        except (ValueError, TypeError):
            a_val = 0.0
        try:
            b_val = float(b_raw)
        except (ValueError, TypeError):
            b_val = 0.0

        operator = self.get_property('operator')
        if operator == 'Add':
            result = a_val + b_val
        elif operator == 'Subtract':
            result = a_val - b_val
        elif operator == 'Multiply':
            result = a_val * b_val
        elif operator == 'Divide':
            result = a_val / b_val if b_val != 0 else 0.0
        elif operator == 'Average':
            result = (a_val + b_val) / 2.0
        else:
            result = 0.0

        # If the computed result changed, update our internal properties and transmit
        if self.value != result:
            self.value = result

            # Update the two text fields so the user sees the numeric result:
            self.set_property('calc_result', str(result))
            self.set_property('value', str(result))  # <= This is the critical step

            # Let downstream nodes know there's new data:
            self.transmit_data(result)

    def on_input_connected(self, input_port, output_port):
        pass

    def on_input_disconnected(self, input_port, output_port):
        pass

    def property_changed(self, property_name):
        pass

    def receive_data(self, data, source_port_name=None):
        pass

    def transmit_data(self, data):
        output_port = self.output(0)
        if output_port and output_port.connected_ports():
            for connected_port in output_port.connected_ports():
                connected_node = connected_port.node()
                if hasattr(connected_node, 'receive_data'):
                    try:
                        # Attempt to convert to int if possible, else float
                        data_int = int(data)
                        connected_node.receive_data(data_int, source_port_name='Result')
                    except ValueError:
                        connected_node.receive_data(data, source_port_name='Result')