import xml.etree.ElementTree as ET
tree = ET.parse('tags.xml')
root = tree.getroot()

channels = {}
unreadable_channels = {}
ignored_channels = {}
writeable_channels = {}

ignore_tags = [
    "cmd_Run",
    "cmd_TimerRun",
    "DH_DischargePressure",
    "DH_DischargeTemperature",
    "DH_VibrationX",
    "DH_VibrationY",
    "DH_WindingTemperature",
    "DigitalInput_Status_0",
    "DigitalInput_Status_1",
    "DigitalInput_Status_2",
    "DigitalInput_Status_3",
    "DigitalInput_Status_4",
    "DigitalInput_Status_5",
    "E300_Config_Buffer",
    "E300_OUTPUT_NUMBER",
    "E300_OUTPUT_SET_CORRECTLY",
    "E300_Output_Enable",
    "E300_Output_Toggled",
    "E300_SCAN_RATE",
    "Enable_IO_Read",
    "Pressure_OOT_Scans",
    "Pressure_OOT_Seconds",
    "Restart_Allowed",
    "Restart_Command",
    "Run_Time",
    "Shutdown_Time"
    "Start_Button",
    "Start_Time",
    "Start_Time_Set",
    "sts_TimerRunTimeSet",
    "sts_TimerCycleActive",
    "sts_TimerWaitTimeSet",
    "sts_TripCountIncreased",
    "time_CurrentTime",
    "time_TimerRunTime",
    "time_TimerWaitTime",
    "Time_Until_Startup",
    "timer_RunTimeLeft",
    "timer_WaitTimeLeft",
    "TripResetWriteStatus",
    "cfg_I_L1LossTripDelay",  # Individual Line tags handled by generic Line tags
    "cfg_I_L1_OvercurrentTripDelay",
    "cfg_I_L1_OvercurrentTripLevel",
    "cfg_I_L1_OvercurrentWarningLevel",
    "cfg_I_L1_UndercurrentTripDelay",
    "cfg_I_L1_UndercurrentTripLevel",
    "cfg_I_L1_UndercurrentWarningLevel",
    "cfg_I_L2LossTripDelay",
    "cfg_I_L2_OvercurrentTripDelay",
    "cfg_I_L2_OvercurrentTripLevel",
    "cfg_I_L2_OvercurrentWarningLevel",
    "cfg_I_L2_UndercurrentTripDelay",
    "cfg_I_L2_UndercurrentTripLevel",
    "cfg_I_L2_UndercurrentWarningLevel",
    "cfg_I_L3LossTripDelay",
    "cfg_I_L3_OvercurrentTripDelay",
    "cfg_I_L3_OvercurrentTripLevel",
    "cfg_I_L3_OvercurrentWarningLevel",
    "cfg_I_L3_UndercurrentTripDelay",
    "cfg_I_L3_UndercurrentTripLevel",
    "cfg_I_L3_UndercurrentWarningLevel",
    "cfg_I_TripEnableCurrent",  # Enables get build by the enable bits
    "cfg_I_WarningEnableCurrent",
    "cfg_P_OverApparentPowerInhibitTime",  # We're not going to worry about the power configuration for this panel
    "cfg_P_OverApparentPowerTripDelay",
    "cfg_P_OverApparentPowerTripLevel",
    "cfg_P_OverApparentPowerWarningLevel",
    "cfg_P_OverPowerFactorLagInhibitTime",
    "cfg_P_OverPowerFactorLagTripDelay",
    "cfg_P_OverPowerFactorLagTripLevel",
    "cfg_P_OverPowerFactorLagWarningLevel",
    "cfg_P_OverPowerFactorLeadInhibitTime",
    "cfg_P_OverPowerFactorLeadTripDelay",
    "cfg_P_OverPowerFactorLeadTripLevel",
    "cfg_P_OverPowerFactorLeadWarningLevel",
    "cfg_P_OverReactiveConsumedInhibitTime",
    "cfg_P_OverReactiveConsumedTripDelay",
    "cfg_P_OverReactiveConsumedTripLevel",
    "cfg_P_OverReactiveConsumedWarningLevel",
    "cfg_P_OverReactiveGeneratedInhibitTime",
    "cfg_P_OverReactiveGeneratedTripDelay",
    "cfg_P_OverReactiveGeneratedTripLevel",
    "cfg_P_OverReactiveGeneratedWarningLevel",
    "cfg_P_OverRealPowerInhibitTime",
    "cfg_P_OverRealPowerTripDelay",
    "cfg_P_OverRealPowerTripLevel",
    "cfg_P_OverRealPowerWarningLevel",
    "cfg_P_TripEnablePower",
    "cfg_P_UnderApparentPowerInhibitTime",
    "cfg_P_UnderApparentPowerTripDelay",
    "cfg_P_UnderApparentPowerTripLevel",
    "cfg_P_UnderApparentPowerWarningLevel",
    "cfg_P_UnderPowerFactorLagInhibitTime",
    "cfg_P_UnderPowerFactorLagTripDelay",
    "cfg_P_UnderPowerFactorLagTripLevel",
    "cfg_P_UnderPowerFactorLagWarningLevel",
    "cfg_P_UnderPowerFactorLeadInhibitTime",
    "cfg_P_UnderPowerFactorLeadTripDelay",
    "cfg_P_UnderPowerFactorLeadTripLevel",
    "cfg_P_UnderPowerFactorLeadWarningLevel",
    "cfg_P_UnderReactiveConsumedInhibitTime",
    "cfg_P_UnderReactiveConsumedTripDelay",
    "cfg_P_UnderReactiveConsumedTripLevel",
    "cfg_P_UnderReactiveConsumedWarningLevel",
    "cfg_P_UnderReactiveGeneratedInhibitTime",
    "cfg_P_UnderReactiveGeneratedTripDelay",
    "cfg_P_UnderReactiveGeneratedTripLevel",
    "cfg_P_UnderReactiveGeneratedWarningLevel",
    "cfg_P_UnderRealPowerInhibitTime",
    "cfg_P_UnderRealPowerTripDelay",
    "cfg_P_UnderRealPowerTripLevel",
    "cfg_P_UnderRealPowerWarningLevel",
    "cfg_P_WarningEnablePower",
    "cfg_V_TripEnableVoltage",
    "cfg_V_WarningEnableVoltage"
]

writeable_tags = [
    "cfg_C_FLASetting",
    "cfg_C_TripEnableControl",
    "cfg_C_WarningEnableControl",
    "cfg_ClearTripCountAfter",
    "cfg_GF_GroundFaultInhibitTime",
    "cfg_GF_GroundFaultTripDelay",
    "cfg_GF_GroundFaultTripLevel",
    "cfg_GF_GroundFaultWarningDelay",
    "cfg_GF_GroundFaultWarningLevel",
    "cfg_I_CTPrimary",
    "cfg_I_CTSecondary",
    "cfg_I_CurrentImbalanceInhibitTime",
    "cfg_I_CurrentImbalanceTripDelay",
    "cfg_I_CurrentImbalanceTripLevel",
    "cfg_I_CurrentImbalanceWarningLevel",
    "cfg_I_JamInhibitTime",
    "cfg_I_JamTripDelay",
    "cfg_I_JamWarningLevel",
    "cfg_I_LineLossInhibitTime",
    "cfg_I_LineLossTripDelay",
    "cfg_I_OvercurrentInhibitTime",
    "cfg_I_OvercurrentTripDelay",
    "cfg_I_OvercurrentTripLevel",
    "cfg_I_OvercurrentWarningLevel",
    "cfg_I_StallEnabledTime",
    "cfg_I_StallTripLevel",
    "cfg_I_UndercurrentInhibitTime",
    "cfg_I_UndercurrentTripDelay",
    "cfg_I_UndercurrentTripLevel",
    "cfg_I_UndercurrentWarningLevel",
    "cfg_I_UnderloadInhibitTime",
    "cfg_I_UnderloadTripDelay",
    "cfg_I_UnderloadTripLevel",
    "cfg_I_UnderloadWarningLevel",
    "cfg_OverloadTripCountLimit",
    "cfg_PL_PhaseLossInhibitTime",
    "cfg_PL_PhaseLossTripDelay",
    "cfg_READ",
    "cfg_SpecificGravity",
    "cfg_TCU_TripClass",
    "cfg_TimerModeEnabled",
    "cfg_TimerRunTime",
    "cfg_TimerWaitTime",
    "cfg_TripCountLimit",
    "cfg_V_OverfrequencyInhibitTime",
    "cfg_V_OverfrequencyTripDelay",
    "cfg_V_OverfrequencyTripLevel",
    "cfg_V_OverfrequencyWarningLevel",
    "cfg_V_OvervoltageInhibitTime",
    "cfg_V_OvervoltageTripDelay",
    "cfg_V_OvervoltageTripLevel",
    "cfg_V_OvervoltageWarningLevel",
    "cfg_V_PTPrimary",
    "cfg_V_PTSecondary",
    "cfg_V_PhaseRotationInhibitTime",
    "cfg_V_PhaseRotationTripType",
    "cfg_V_UnderfrequencyInhibitTime",
    "cfg_V_UnderfrequencyTripDelay",
    "cfg_V_UnderfrequencyTripLevel",
    "cfg_V_UnderfrequencyWarningLevel",
    "cfg_V_UndervoltageInhibitTime",
    "cfg_V_UndervoltageTripDelay",
    "cfg_V_UndervoltageTripLevel",
    "cfg_V_UndervoltageWarningLevel",
    "cfg_V_VoltageImbalanceInhibitTime",
    "cfg_V_VoltageImbalanceTripDelay",
    "cfg_V_VoltageImbalanceTripLevel",
    "cfg_V_VoltageImbalanceWarningLevel",
    "cfg_V_VoltageMode",
    "cfg_WRITE",
    "Downtime_Time_Parameter",
    "Downtime_Time_Parameter_OL",
    "Downhole_Tool_Enabled",
    "Pressure_Alarm_Delay",
    "Pressure_Alarm_Startup_Delay",
    "Pressure_EU_Max",
    "Pressure_EU_Min",
    "Pressure_Hi_SP",
    "Pressure_Lo_SP",
    "Pressure_Shutdown",
    "Pressure_Shutdown_Enabled",
    "Pressure_Startup",
    "Pressure_Startup_Enabled",
    "Pressure_Switch_Enabled",
    "Pressure_Transducer_Enabled",
    "Start_Command",
    "Stop_Command",
    "Temp_Shutdown",
    "Temp_Shutdown_Enabled",
    "Temp_Startup",
    "Temp_Startup_Enabled",
    "TripEnable_V_Overfrequency",
    "TripEnable_V_Overvoltage",
    "TripEnable_V_PhaseRotation",
    "TripEnable_V_Underfrequency",
    "TripEnable_V_Undervoltage",
    "TripEnable_V_VoltageUnbalance",
    "TripEnabled_I_CurrentImbalance",
    "TripEnabled_I_GroundFault",
    "TripEnabled_I_Jam",
    "TripEnabled_I_LineLoss",
    "TripEnabled_I_Overcurrent",
    "TripEnabled_I_Overload",
    "TripEnabled_I_PhaseLoss",
    "TripEnabled_I_Stall",
    "TripEnabled_I_Undercurrent",
    "TripEnabled_I_Underload",
    "TripResetCmd",
    "WarningEnable_V_Overfrequency",
    "WarningEnable_V_Overvoltage",
    "WarningEnable_V_PhaseRotation",
    "WarningEnable_V_Underfrequency",
    "WarningEnable_V_Undervoltage",
    "WarningEnable_V_VoltageUnbalance",
    "WarningEnabled_I_CurrentImbalance",
    "WarningEnabled_I_GroundFault",
    "WarningEnabled_I_Jam",
    "WarningEnabled_I_LineLoss",
    "WarningEnabled_I_Overcurrent",
    "WarningEnabled_I_Overload",
    "WarningEnabled_I_PhaseLoss",
    "WarningEnabled_I_Stall",
    "WarningEnabled_I_Undercurrent",
    "WarningEnabled_I_Underload",


]


for child in root:
    try:
        tagName = child[1].text
        tagType = child[2].text
        struct = {
            'tag': tagName,
            "last_value": "",
            "data_type": tagType,
            "change_amount": .5,
            "last_time_uploaded": 0,
            "max_time_between_uploads": 3600
        }
        if tagName in writeable_tags:
            struct['read_only'] = False
        else:
            struct['read_only'] = True

        if tagName[0:3] == "cfg":
            struct['max_time_between_uploads'] = 86400

        chName = tagName.replace("_", "")  # Channel names cannot have underscores
        chName = chName.lower()  # Channel names should all start wth a lowercase letter

        if len(chName) > 30:
            chName = chName[0:30]

        if tagName not in ignore_tags:
            if tagType == "BOOL":
                struct['change_amount'] = None
                channels[chName] = struct
            elif tagType == "REAL" or tagType[-3:] == "INT":
                channels[chName] = struct
            else:
                unreadable_channels[chName] = struct
        else:
            ignored_channels[chName] = struct

        if struct['read_only'] is False:
            writeable_channels[chName] = struct
    except Exception, e:
        print "oops: {}".format(e)

with open('ipp_channels_setup.py', 'wb') as txtFile:
    txtFile.write("import pickle\r\r")
    txtFile.write("channels = {\r")
    for x in sorted(channels):
        c = channels[x]
        txtFile.write("\t'{}': {{\r".format(x))
        txtFile.write("\t\t'data_type': '{}',\r".format(c['data_type']))
        txtFile.write("\t\t'change_amount': {},\r".format(c['change_amount']))
        txtFile.write("\t\t'max_time_between_uploads': {},\r".format(c['max_time_between_uploads']))
        txtFile.write("\t\t'tag': '{}',\r".format(c['tag']))
        txtFile.write("\t\t'last_time_uploaded': {},\r".format(c['last_time_uploaded']))
        txtFile.write("\t\t'last_value': '{}',\r".format(c['last_value']))
        txtFile.write("\t},\r")

    txtFile.write("}\r")
    txtFile.write("\rwith open('ipp_channels.p', 'wb') as ch_f:\r")
    txtFile.write("\tpickle.dump(channels, ch_f)\r\r")

with open('channels.txt', 'wb') as ch_txt:
    for x in sorted(channels):
        c = channels[x]
        rw = 'read only'
        if c['read_only'] is False:
            rw = "WRITEABLE"
        ch_txt.write('[] - {} - {} - {}\r'.format(x, c['data_type'], rw))

print("UNREADABLE CHANNELS: ")
for y in sorted(unreadable_channels):
    print("{} - {}".format(unreadable_channels[y]['data_type'], y))

print("")
print("")
print("")
print("IGNORED CHANNELS: ")
for z in sorted(ignored_channels):
    print("{} - {}".format(z, ignored_channels[z]['data_type']))

with open('writeFunctions.txt', 'wb') as wftxt:
    for a in sorted(writeable_channels):
        c = writeable_channels[a]
        wftxt.write("def ipp_{0}(self, name, value):\r".format(a.replace("_", "").lower()))
        wftxt.write("\tprint('trying to set {0} to {{}}'.format(value))\r".format(c['tag']))
        if c['data_type'] == 'REAL':
            wftxt.write("\treturn u800.writeMicroTag(addr, '{0}', float(value))\r".format(c['tag']))
        elif (c['data_type'] == 'BOOL') or (c['data_type'][-3:] == "INT"):
            wftxt.write("\treturn u800.writeMicroTag(addr, '{0}', int(value))\r".format(c['tag']))
        else:
            print("!!!! DIDNT WORK FOR {0}".format(c))
        wftxt.write("\r")
