import enum


class ServiceId:
    current_powertrain_diagnostics_data = 0x01
    powertrain_freeze_frame_data = 0x02
    emission_related_dtcs = 0x03
    reset_emission_related_dtcs = 0x04
    oxygen_sensor_monitoring_test_results = 0x05
    on_board_monitoring_test_results = 0x06
    pending_emission_related_dtcs = 0x07
    control_on_board_system_test_or_component = 0x08
    vehicle_information = 0x09
    permanent_emission_related_dtcs = 0x0A

    diagnostic_session_control = 0x10
    ecu_reset = 0x11
    clear_diagnostic_information = 0x14
    read_dtc_information = 0x19

    read_data_by_identifier = 0x22
    read_memory_by_address = 0x23
    read_scaling_data_by_identifier = 0x24
    security_access = 0x27
    communication_control = 0x28
    authentication = 0x29
    read_data_by_periodic_identifier = 0x2A
    dynamically_define_data_identifier = 0x2C
    write_data_by_identifier = 0x2E
    input_output_control_by_identifier = 0x2F

    routine_control = 0x31
    request_download = 0x34
    request_upload = 0x35
    transfer_data = 0x36
    request_transfer_exit = 0x37
    request_file_transfer = 0x38
    write_memory_by_address = 0x3D
    tester_present = 0x3E

    negative_response_code = 0x7F

    secured_data_transmission = 0x84
    control_dtc_setting = 0x85
    response_on_event = 0x86
    link_control = 0x87

    kwp_read_freeze_frame_data = 0x12
    kwp_read_diagnostic_trouble_code = 0x13
    kwp_read_status_of_dtcs = 0x17
    kwp_read_dtcs_by_status = 0x18
    kwp_read_ecu_identification = 0x1A

    kwp_start_diagnostic_session = 0x10
    kwp_stop_diagnostic_session = 0x20
    kwp_read_data_by_local_identifier = 0x21
    kwp_wet_data_rates = 0x26
    kwp_enable_normal_message_transmission = 0x29

    kwp_input_output_control_by_local_identifier = 0x30
    kwp_stop_routine_by_local_identifier = 0x32
    kwp_request_routine_results_by_local_identifier = 0x33
    kwp_start_routine_by_address = 0x38
    kwp_stop_routine_by_address = 0x39
    kwp_request_routine_results_by_address = 0x3A
    kwp_write_data_by_local_identifier = 0x3B
    kwp_tester_present = 0x3E

    kwp_start_communication = 0x81
    kwp_stop_communication = 0x82
    kwp_access_timing_parameters = 0x83
    kwp_network_configuration = 0x84


class NegativeResponseCode(enum.IntEnum):
    general_reject = 0x10
    service_not_supported = 0x11
    sub_function_not_supported = 0x12
    incorrect_message_length_or_invalid_format = 0x13
    response_too_long = 0x14

    busy_repeat_request = 0x21
    conditions_not_correct = 0x22
    kwp_routine_not_complete_or_service_in_process = 0x23
    request_sequence_error = 0x24
    no_response_from_subnet_component = 0x25

    request_out_of_range = 0x31
    security_access_denied = 0x33
    invalid_key = 0x35
    exceed_number_of_attempts = 0x36
    required_time_delay_not_expired = 0x37

    kwp_download_not_accepted = 0x40
    kwp_improper_download_type = 0x41
    kwp_can_not_download_to_specified_address = 0x42
    kwp_can_not_download_number_of_bytes_requested = 0x43

    kwp_upload_not_accepted = 0x50
    kwp_improper_upload_type = 0x51
    kwp_can_not_upload_from_specified_address = 0x52
    kwp_can_not_upload_number_of_bytes_requested = 0x53

    upload_download_not_accepted = 0x70
    transfer_data_suspended = 0x71
    general_programming_failure = 0x72
    wrong_block_sequence_counter = 0x73
    kwp_block_transfer_data_checksum_error = 0x77
    request_correctly_received_response_pending = 0x78
    sub_function_not_supported_in_active_session = 0x7E
    service_not_supported_in_active_session = 0x7F

    kwp_service_not_supported_in_active_diag_mode = 0x80
    rpm_too_high = 0x81
    rpm_too_low = 0x82
    engine_is_running = 0x83
    engine_is_not_running = 0x84
    engine_run_time_too_low = 0x85
    temperature_too_high = 0x86
    temperature_too_low = 0x87
    vehicle_speed_too_high = 0x88
    vehicle_speed_too_low = 0x89
    throttle_pedal_too_high = 0x8A
    throttle_pedal_too_low = 0x8B
    transmission_range_not_in_neutral = 0x8C
    transmission_range_not_in_gear = 0x8D
    brake_switch_not_closed = 0x8F

    shifter_lever_not_in_park = 0x90
    torque_converter_clutch_locked = 0x91
    voltage_too_high = 0x92
    voltage_too_low = 0x93

    gateway_locked_communication = 0xF1

    kwp_checksum_error = 0xFA
    kwp_ecu_erasing_flash = 0xFB
    kwp_ecu_programming_flash = 0xFC
    kwp_erasing_error = 0xFD
    kwp_programming_error = 0xFE

    undefined = 0xDE


class DiagnosticSessionType(enum.IntEnum):
    default = 0x01
    programming = 0x02
    extended = 0x03
    safety_system = 0x04

    vw_end_of_line = 0x40
    coding_session = 0x41
    swt_session = 0x42
    hdd_download_session = 0x43
    rsu_session = 0x44
    bosch_develop = 0x4F
    zf_reprogramming = 0x61
    incircuit_programming = 0x6B

    kwp_default = 0x81
    kwp_upload = 0x82
    kwp_download = 0x83
    kwp_programming = 0x84
    kwp_development = 0x85
    kwp_adjustment = 0x86
    kwp_vehicle_upload = 0x87
    kwp_vehicle_download = 0x89
    kwp_vehicle_customer_service_upload = 0x90
    kwp_vehicle_customer_service_download = 0x91
    kwp_end_customer_service_upload = 0x92
    kwp_end_customer_service_download = 0x93

    undefined = 0xFF


class DynamicallyDefineDataIdentifierDefinitionType(enum.IntEnum):
    define_by_identifier = 0x01
    define_by_memory_address = 0x02
    clear = 0x03


class RoutineControlType(enum.IntEnum):
    start_routine = 0x01
    stop_routine = 0x02
    request_routine_results = 0x03


class EcuResetType(enum.IntEnum):
    hard_reset = 0x01
    key_off_on_reset = 0x02
    soft_reset = 0x03
    enable_rapid_power_shutdown = 0x04
    disable_rapid_power_shutdown = 0x05
    kwp_send_reset_status = 0x80


class CommunicationControlType(enum.IntEnum):
    enable_rx_and_tx = 0x00
    enable_rx_and_disable_tx = 0x01
    disable_rx_and_enable_tx = 0x02
    disable_rx_and_tx = 0x03
    enable_rx_and_disable_tx_by_address = 0x04
    enable_rx_and_tx_by_address = 0x05


class CommunicationType(enum.IntEnum):
    normal_communication_messages = 0x01
    network_management_communication_messages = 0x02
    all = 0x03


class DTCSettingType(enum.IntEnum):
    on = 0x01
    off = 0x02


class TesterPresentType(enum.IntEnum):
    send_response = 0x00
    do_not_respond = 0x80


class ReadDTCReportType(enum.IntEnum):
    report_number_of_dtc_by_status_mask = 0x01
    report_dtc_by_status_mask = 0x02
    report_dtc_snapshot_identification = 0x03
    report_dtc_snapshot_record_by_dtc_number = 0x04
    report_dtc_stored_data_by_record_number = 0x05
    report_dtc_ext_data_record_by_dtc_number = 0x06
    report_number_of_dtc_by_severity_mask_record = 0x07
    report_dtc_by_severity_mask_record = 0x08
    report_severity_information_of_dtc = 0x09
    report_supported_dtc = 0x0A
    report_first_test_failed_dtc = 0x0B
    report_first_confirmed_dtc = 0x0C
    report_most_recent_test_failed_dtc = 0x0D
    report_most_recent_confirmed_dtc = 0x0E
    report_dtc_fault_detection_counter = 0x14
    report_dtc_with_permanent_status = 0x15
    report_dtc_ext_data_record_by_record_number = 0x16
    report_dtc_user_def_memory_dtc_by_status_mask = 0x17
    report_user_def_memory_dtc_snapshot_record_by_dtc_number = 0x18
    report_user_def_memory_dtc_ext_data_record_by_dtc_number = 0x19
    report_dtc_extended_data_record_identification = 0x1A
    report_wwh_obd_dtc_by_mask_record = 0x42
    report_wwh_obd_dtc_with_permanent_status = 0x55
    report_dtc_information_by_dtc_readiness_group_identifier = 0x56


class DataType(enum.Enum):
    ubyte = "UBYTE"
    sbyte = "SBYTE"
    uword = "UWORD"
    sword = "SWORD"
    unspecified = "unspecified"

    @property
    def length(self) -> int:
        if self is DataType.ubyte:
            return 1
        if self is DataType.sbyte:
            return 1
        if self is DataType.uword:
            return 2
        if self is DataType.sword:
            return 2
        return 0


class ISOTP:
    frame_length = 8
    maximum_frame_size = 0xFFF
    maximum_data_transfer_size = 0xFFF


class KWP:
    ecu_identification_data_table = 0x80
    ecu_identification_scaling = 0x81
    ecu_identification_vin = 0x90
