'''Validates that the softlinks for cram are setup correctly for IOC/HLA applications and PyDM displays. Use this to determine why an '''
from __future__ import print_function

import os
import sys
import argparse
import globals
import toolconfig
import multi_facility_process_helper_client
import json
import listCurrentReleases
from globals import UserParamsException

def printChanges(ioc, changes, count):
    if len(changes) <=0:
        return
    print(ioc)
    if count < 0:
        count = len(changes)
    for change in changes[:count]:
        print("--> {0} on {1} by {2}".format(change['release'], change['datetime'], change['user']))

def validateLinks(name, type, facility, ioc):
    '''Validates that the softlinks are set up correctly for the application/IOC.
    '''
    if type in ['SIOC', 'HIOC']:
        commandsAndArgs = []
        commandsAndArgs.append(('ls', [os.path.join(toolconfig.determineReleaseFolder(facility, name, type), name)]))
        commandsAndArgs.append(('ls', [os.path.join(toolconfig.determineLinkFolder(facility, name, type), ioc)]))
        results = multi_facility_process_helper_client.executeCommandsOnFacility(facility, commandsAndArgs)
        if not results[0]:
            print("Cannot determine the contents of iocTop for {0} in facility {1}".format(name, facility))
            return
        if not results[1]:
            print("Cannot determine the contents of iocCommon for {0} in facility {1}".format(ioc, facility))
            return
        if globals.verbose:
            print(json.dumps(results))
        iocTopContents = results[0]
        iocCommonContents = results[1]
        currentFound = False
        for fileInfo in iocTopContents:
            if fileInfo['name'] == 'current':
                print("Found the current folder for {0} in iocTop".format(name))
                currentFound = True
                if 'pointingTo' not in fileInfo:
                    print("\033[1;31m***\033[0mFound current but it does seem to be a softlink")
                else:
                    pointingTo = fileInfo['pointingTo']
        if not currentFound:
            print("\033[1;31m***\033[0mCannot find the current softlink for package {0} in facility {1}".format(name, facility))
        else:
            if pointingTo:
                if len(pointingTo.rsplit('/')) > 1:
                    print("\033[1;31m***\033[0mFound the current link pointing to a folder outside iocTop {0}".format(pointingTo))
                else:
                    print("The current link exists and looks fine; pointing to {0}".format(pointingTo))
        iocSpecificReleaseFound = False
        for fileInfo in iocCommonContents:
            if fileInfo['name'] == 'iocSpecificRelease':
                print("Found the iocSpecificRelease softlink for {0} in iocCommon".format(ioc))
                iocSpecificReleaseFound = True
                if 'pointingTo' not in fileInfo:
                    print("\033[1;31m***\033[0mFound iocSpecificRelease but it does seem to be a softlink")
                else:
                    iocPointingTo = fileInfo['pointingTo']
        if not iocSpecificReleaseFound:
            print(
            "\033[1;31m***\033[0mCannot find the iocSpecificRelease softlink for IOC ", ioc, "in facility", facility)
        else:
            if iocPointingTo:
                normalizedPath = os.path.normpath(os.path.join(toolconfig.determineLinkFolder(facility, name, type), name, os.path.join(iocPointingTo)))
                if globals.verbose:
                    print("iocSpecificRelease normalized {0}".format(normalizedPath))
                if os.path.dirname(normalizedPath) != os.path.join(toolconfig.determineReleaseFolder(facility, name, type), name):
                    print(
                    "\033[1;31m***\033[0mFound the iocSpecificRelease link but it seems to be pointing to somewhere outside iocTop for package",
                    name, " -- it seems to be pointing here", normalizedPath)
                else:
                    print("The iocSpecificRelease link exists and looks fine; pointing to {0}".format(normalizedPath))
    else:
        # For PyDM displays, the link name is the subsystem, without "pydm-"
        if type == 'PyDM' and name.startswith('pydm-'):
            linkName = name.replace('pydm-', '', 1)
        else:
            linkName = name
        releaseFolder = toolconfig.determineReleaseFolder(facility, name, type)
        linkFolder = toolconfig.determineLinkFolder(facility, name, type)
        if not releaseFolder or not linkFolder:
            print("Type {0} does not exist for facility {1} in the global facility config".format(type, facility))
            return
        commandsAndArgs = []
        commandsAndArgs.append(('ls', [os.path.join(releaseFolder, name)]))
        commandsAndArgs.append(('ls', [os.path.join(linkFolder)]))
        results = multi_facility_process_helper_client.executeCommandsOnFacility(facility, commandsAndArgs)
        if not results[0]:
            print("Cannot determine the contents of the package folder for {0} in facility {1}".format(name, facility))
            return
        if not results[1]:
            print("Cannot determine the contents of the link folder for {0} in facility {1}".format(ioc, facility))
            return
        if globals.verbose:
            print(json.dumps(results))
        releaseFolderContents = results[0]
        linkFolderContents = results[1]
        # For PyDM displays, the link name is the subsystem, without "pydm-"
        if type == 'PyDM' and name.startswith('pydm-'):
            linkName = name.replace('pydm-', '', 1)
        else:
            linkName = name
        currentFound = False
        for fileInfo in linkFolderContents:
            if fileInfo['name'] == linkName:
                print("Found the package link for {0} in the link folder".format(name))
                currentFound = True
                if 'pointingTo' not in fileInfo:
                    print("\033[1;31m***\033[0mFound the package link but it does seem to be a softlink")
                else:
                    pointingTo = fileInfo['pointingTo']
        if not currentFound:
            print("\033[1;31m***\033[0mCannot find the package link for package {0} in facility {1}".format(name, facility))
        else:
            if pointingTo:
                normalizedPath = os.path.normpath(os.path.join(toolconfig.determineLinkFolder(facility, name, type), os.path.join(pointingTo)))
                if globals.verbose:
                    print("iocSpecificRelease normalized {0}".format(normalizedPath))
                if os.path.dirname(normalizedPath) != os.path.join(toolconfig.determineReleaseFolder(facility, name, type), name):
                    print(
                    "\033[1;31m***\033[0mFound the package link but it seems to be pointing to somewhere outside the release folder for package",
                    name, " -- it seems to be pointing here", normalizedPath)
                else:
                    print("The package link exists and looks fine; pointing to {0}".format(normalizedPath))
        

def execute(args):
    parser = argparse.ArgumentParser(prog="cram validatelinks")
    parser.add_argument('-v', '--verbose', action='store_true', help='Enable verbose logging')
    parser.add_argument('-n', '--name', help='Specify the application name; we automatically pick this up from the package info if we are running this command in the folder containing the release')
    parser.add_argument('-t', '--type', help='Specifies the type of application from the deployment perspective. Possible values are ' + ", ".join(toolconfig.appTypes.keys()))
    parser.add_argument('-f', '--facility', help='Look in this facility for the IOC/application. Possible values are - ' + ", ".join(toolconfig.getListOfFacilities()) + ".")
    parser.add_argument('-i', '--ioc', help='Specifies the name of the IOC that we want to validate.')
    
    args = parser.parse_args(args)
    globals.verbose = args.verbose
    facility = args.facility
    if facility not in toolconfig.getListOfFacilities():
        print("Please specify a facility from {0}".format(", ".join(toolconfig.getListOfFacilities())))
        return
    packageInfo = toolconfig.determinePackageInfoFromArgs(args)
    name = packageInfo['name']
    type = packageInfo['type']
    ioc = None
    if type in ['SIOC', 'HIOC']:
        ioc = args.ioc
        if not ioc:
            print(
                "For IOC applications, please specify the name of the IOC that you want to validate using the --ioc argument.")
            return
    validateLinks(name, type, facility, ioc)
    


if __name__ == "__main__":
    execute(sys.argv[1:])

