'''Validates that the softlinks for cram are setup correctly for IOC and HLA applications. 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:
        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]
        currentFound = False
        for fileInfo in linkFolderContents:
            if fileInfo['name'] == name:
                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:])

