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

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 "-->", change['release'], "on", change['datetime'], "by", 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", name, "in facility", facility
            return
        if not results[1]:
            print "Cannot determine the contents of iocCommon for", ioc, "in facility", 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", name, "in iocTop"
                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 ", name, "in facility", facility
        else:
            if pointingTo:
                if len(pointingTo.rsplit('/')) > 1:
                    print "\033[1;31m***\033[0mFound the current link pointing to a folder outside iocTop",pointingTo
                else:
                    print "The current link exists and looks fine; pointing to", pointingTo
        iocSpecificReleaseFound = False
        for fileInfo in iocCommonContents:
            if fileInfo['name'] == 'iocSpecificRelease':
                print "Found the iocSpecificRelease softlink for", ioc, "in iocCommon"
                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",  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", 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
        commandsAndArgs = []
        commandsAndArgs.append(('ls', [os.path.join(toolconfig.determineReleaseFolder(facility, name, type), name)]))
        commandsAndArgs.append(('ls', [os.path.join(toolconfig.determineLinkFolder(facility, name, type))]))
        results = multi_facility_process_helper_client.executeCommandsOnFacility(facility, commandsAndArgs)
        if not results[0]:
            print "Cannot determine the contents of the package folder for", name, "in facility", facility
            return
        if not results[1]:
            print "Cannot determine the contents of the link folder for", ioc, "in facility", 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", name, "in the link folder"
                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 ", name, "in facility", 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",  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", 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", ", ".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:])

