from can.interfaces.vector import VectorBus
from udsoncan.connections import *
import isotp
from udsoncan.client import Client
import cantools
from udsoncan import DataIdentifier, IOValues
from udsoncan.configs import default_client_config

DATATYPES = {
    1: "B",
    2: "H",
    3: "I",
    4: "I",
    8: "Q",
}

DATATYPES_REAL = {
    4: "f",
    8: "d"
}


def get_size_and_order(did):
    data = ""
    if len(did.datas) == 0:
        return '<H'
    byte_order = did.datas[0].byte_order
    bo = '<' if byte_order == "little_endian" else '>'
    data += bo

    for dids in did.datas:
        size = int(dids.length/8)
        if dids.is_float:
            dt = DATATYPES_REAL[size]
        else:
            dt = DATATYPES[size]
            if dids.is_signed:
                dt.lower()
        data += dt

    return data


def create_config_dict(database, config):
    for did in database.dids:
        data_type = get_size_and_order(did=did)
        if did.identifier == 0:
            pass
        else:
            config["data_identifiers"].update({did.identifier: data_type})
            config["input_output"].update({did.identifier: data_type})

    return config


class UDSclass:
    def __init__(self, client):
        self.client = client

    def read_data(self, client, database, name=None, did_ident=None):
        try:
            if name:
                did = database.get_did_by_name(name)
                response = client.read_data_by_identifier(didlist=did.identifier)
                return response.data

            if did_ident:
                did = database.get_did_by_identifier(did_ident)
                response = client.read_data_by_identifier(didlist=did.identifier)
                return response.data

            return

        except Exception as e:
            print(e)
            print("Failed to read data")
            exit()

    def write_data(self, client, database, value, name=None, did_ident=None):
        try:
            if name:
                did = database.get_did_by_name(name)
                client.write_data_by_identifier(did=did.identifier, value=value)

            if did_ident:
                did = database.get_did_by_identifier(did_ident)
                client.write_data_by_identifier(did=did.identifier, value=value)

        except Exception as e:
            print(e)
            print("Failed to write data")
            exit()

    def io_control_write(self, client, database, values, name=None, did_ident=None):
        try:
            if name:
                did = database.get_did_by_name(name)
                client.io_control(did=did.identifier, control_param=3, values=list(values))

            if did_ident:
                did = database.get_did_by_identifier(did_ident)
                client.io_control(did=did.identifier, control_param=3, values=list(values))

        except Exception as e:
            print(e)
            print("Failed the io_control write data")
            exit()
