import websockets
import json

class EmscopeConnection:

    # Valid device configuration values
    possible_values = [
        "values",
        "SN",
        "SFP_SN",
        "measurement_uncertainty",
        "num_points",
        "measure_channel",
        "detector_type",
        "trace_type",
        "average",
        "rbw",
        "mode",
        "reference_level",
        "input_attenuator",
        "input_attenuator_auto_value",
        "amp_units",
        "sweep_time",
        "standards",
        "report",
        "get_temps",
        "external_loss",
        "overload",
        "temperatures",
        "session_UUID",
        "MAC",
        "threephase",
        "visible",
        "osc_us_div",
        "osc_volts_div",
        "osc_sweep",
        "trigger",
        "osc_trigger_offset",
        "osc_trigger_level",
        "osc_vertical_offset",
        "osc_horizontal_offset",
        "repetition",
        "display_range"
    ]

    # Values limited to read only operations
    read_only_values = [
        "values",
        "SN",
        "SFP_SN",
        "num_points",
        "input_attenuator_auto_value",
        "standards",
        "report",
        "get_temps",
        "overload",
        "temperatures",
        "MAC",
        "repetition"
    ]


    def __init__(self, url):

        self.resetValues()
        
        self.url = url
        #self.callback = callback
        #self.rawcallback = rawcallback

        self.emscope_parser = False


    async def disconnect(self):
        return await self.websocket.close()

    async def connect(self):
        self.websocket = await websockets.connect(self.url)


    # Parses received data and returns the parsed JSON
    async def parseMessages(self):
        # Get new messages
        rcv = await self.websocket.recv()
        # Parse the JSON data
        rec_data = json.loads(rcv)

        # Check possible data received. Change corresponding values and add the name to the received_info array
        for key in rec_data:

            # Special case for input_attenuator
            if key == "input_attenuator":
                self.input_attenuator_auto_value = rec_data[key]
                break

            # Allow only valid keys
            if key in self.possible_values:
                setattr(self, key, rec_data[key])
            else:
                print("ERROR: Received unknown key:", key)
        
        return rec_data


    # Initializes the default values for vars
    def resetValues(self):

        self.SN = ""
        self.SFP_SN = ""
        self.measurement_uncertainty = ""
        self.num_points = ""
        self.measure_channel = "lg"
        self.detector_type = "pk"
        self.trace_type = "clearwrite"
        self.average = "10"
        self.rbw = "9"
        self.mode = "circuit"
        self.reference_level = 0 # TO DO
        self.input_attenuator = "auto"
        self.input_attenuator_auto_value = ""
        self.amp_units = "dbm"
        self.standards = []
        self.report = []
        self.overload = []
        self.threephase = False

        self.values = {} # Last read values are empty


    async def setRBW(self, rbw, threephase = False):
        # Set object variable value
        self.rbw = rbw
        self.threephase = threephase

        # Create object, populate, JSONize and send to WS
        json_object = ()

        json_object = { "rbw": rbw, "threephase": threephase }

        json_text = json.dumps(json_object)

        await self.websocket.send(json_text)



    # Setter of values for object and server
    async def setValue(self, field, val):

        if not field in self.possible_values or field in self.read_only_values: # Check if field is valid
            print("getValue error: attemping to change field " + field)
            return False

        # Set object variable value
        setattr(self, field, val)

        # Create object, populate, JSONize and send to WS
        json_object = ()

        json_object = { field: val }

        json_text = json.dumps(json_object)

        await self.websocket.send(json_text)


    # Getter of values for server
    async def getValue(self, field, val):

        if not field in self.read_only_values: # Check if field is valid
            print("getValue error: attemping to get field " + field)
            return False

        #Create object, populate, JSONize and send to WS
        json_object = ()
        json_object = { field: val }
        json_text = json.dumps(json_object)


        await self.websocket.send(json_text)


    # Request standards
    async def updateStandardsList(self):
        await self.websocket.send('{"get_standards": true}')
