#!/usr/bin/env python
#==============================================================
#
#  Abs:   Module for sorting screeniocs
#
#  Name:  sortScreenIOCS.py
#
#  Rem:   This module sorts the screen IOCs file. The main
#         method is sortScreenIOCs. Adapted from
#         parseScreenIOCS.py by M. Shankar (mshankar).
#  Rem:   This module sorts the  screeniocs file in the
#         following order:
#
#           - terminal servers in order of port
#           - all SIOC types
#           - all VIOC types
#
#  Facility: SLAC Controls
#
#  Auth:  05-Aug-2019, A. Le (anle)
#--------------------------------------------------------------
#  Mods: (Latest to oldest)
#     22-Mar-2024, A. Le (anle)
#         Support both new and old screeniocs formats
#     26-Aug-2019, A. Le (anle)
#         Clean up screeniocs output
#
#==============================================================
#
import os
import sys
from operator import itemgetter
from tables import make_table

scriptPath = os.path.expandvars("$TOOLS/script")
sys.path.append(scriptPath)
from parseScreenIOCS import parseScreenIOCs, getScreenIOCsFormat

def sortScreenIOCs(tempScreenIOCsPath, sortedScreenIOCsPath):
    '''Sorts IOCs by the following scheme:
    - HIOC: terminal server, then port
    - SIOC: executable, then name
    - VIOC: executable, terminal server, then name

    Each entry must follow the correct format:
    - HIOC: alias, terminal server, port, host screen, description
    - SIOC: alias, path, ioc type, host screen, description
    - VIOC: alias, host screen, users, path (optional), description
    '''
    # Collect IOCs from screeniocs
    iocListsByType = {
        'HIOC': [],
        'SIOC': [],
        'VIOC': []
    }
    iocInfos = parseScreenIOCs(tempScreenIOCsPath)
    for ioc in iocInfos:
        iocInfo = iocInfos[ioc]
        iocListsByType[iocInfo['type']].append(iocInfo)

    # Arrange IOC info into table data
    hiocList = []
    siocList = []
    viocList = []
    screenIOCsFormat = getScreenIOCsFormat(tempScreenIOCsPath)
    # TODO: move logic to parseScreenIOCS
    for iocInfo in sorted(iocListsByType['HIOC'], key=itemgetter('terminalserver', 'port')):
        if screenIOCsFormat == 0:
            entry = [iocInfo['name'], iocInfo['terminalserver'], iocInfo['port'], iocInfo['screenhost'], iocInfo.get('description', '')]
        else:
            iocOwner = os.path.expandvars("$IOC_OWNER")
            screenHostInfo = "{}@{}".format(iocOwner, iocInfo['screenhost'])
            terminalServerInfo = "root@{}:{}".format(iocInfo['terminalserver'], iocInfo['port'])
            entry = [iocInfo['type'], iocInfo['name'], screenHostInfo, terminalServerInfo, iocInfo.get('description', '')]
        hiocList.append(entry)
    for iocInfo in sorted(iocListsByType['SIOC'], key=itemgetter('executable', 'name')):
        if screenIOCsFormat == 0:
            entry = [iocInfo['name'], iocInfo['executable'], "sioc", iocInfo['screenhost'], iocInfo.get('description', '')]
        else:
            iocOwner = os.path.expandvars("$IOC_OWNER")
            screenHostInfo = "{}@{}".format(iocOwner, iocInfo['screenhost'])
            entry = [iocInfo['type'], iocInfo['name'], screenHostInfo, iocInfo['executable'], iocInfo.get('description', '')]
        siocList.append(entry)
    for iocInfo in sorted(iocListsByType['VIOC'], key=itemgetter('executable', 'terminalserver', 'name') if 'executable' in iocListsByType['VIOC'] else itemgetter('terminalserver', 'name')):
        if screenIOCsFormat == 0:
            entry = [iocInfo['name'], iocInfo['terminalserver'], iocInfo['user'], iocInfo.get('description', '')]
        else:
            cpuInfo = "{}@{}".format(iocInfo['user'], iocInfo['terminalserver'])
            entry = [iocInfo['type'], iocInfo['name'], cpuInfo, iocInfo.get('executable', ''), iocInfo.get('description', '')]
        if 'executable' in iocInfo:
            entry.insert(-1, iocInfo['executable'])
        viocList.append(entry)

    # Generate pretty tables
    tables = make_table(hiocList) + make_table(siocList) + make_table(viocList)

    # Grab header from old screeniocs
    headerLines = []
    with open(tempScreenIOCsPath, 'r') as f:
        for line in f:
            if line.startswith("#") or line == "\n":
                headerLines.append(line)
            else:
                break

    # Write to new screeniocs
    with open(sortedScreenIOCsPath, 'w') as f:
        # Add header
        f.writelines(headerLines)

        # Write IOC tables
        f.write(tables)

        # Add end of file commit
        f.write("\n")
        f.write("# End of file\n")
