#! /usr/bin/env python

# Copyright (c) Members of the EGEE Collaboration. 2004. 
# See http://www.eu-egee.org/partners/ for details on the copyright
# holders.  
# 
# Licensed under the Apache License, Version 2.0 (the "License"); 
# you may not use this file except in compliance with the License. 
# You may obtain a copy of the License at 
# 
#     http://www.apache.org/licenses/LICENSE-2.0 
# 
# Unless required by applicable law or agreed to in writing, software 
# distributed under the License is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
# See the License for the specific language governing permissions and 
# limitations under the License.

"""
***************************************************************************
    filename  : glite-wms-job-status
    author    : Alessandro Maraschini, Alvise Dorigo
    email     : alvise.dorigo@pd.infn.it
    copyright : (C) 2004 by DATAMAT
***************************************************************************
//
// $Id$
//
"""
# Initial Check: try to find UI configuration file path
import sys
import os.path
import os
import re


try:
        path=os.environ['EMI_UI_CONF']+"/usr"
except:
        path="/usr"



# append lib/lib64 directories to search path
for app in ["lib","lib64"]:
        for bpp in ["",os.sep+"python"]:
                libPath=path+os.sep+app+bpp
                sys.path.append(libPath)

import wmsui_utils
import wmsui_checks
import time
#common methods
from glite_wmsui_LbWrapper import Status
import wmsui_api
from wmsui_utils import errMsg
from wmsui_utils import dbgMsg
from wmsui_utils import exit

from signal import *

# Catch user interrupt ^C
signal(SIGINT, wmsui_utils.ctc)


def checkExclude(includes, excludes):
	if includes and excludes:
		errMsg('Error','UI_ARG_EXCLUSIVE', "--status" , "--exclude")
		return [1,0,0]
	OPT= "--status"
	#index of lud in the actual list
	for ludes in [includes , excludes]:
		i = 0
		for lud in ludes:
			try:
				ludes[i]= int(lud)
				if ludes[i] >=wmsui_api.STATE_CODE_MAX:
					errMsg ( "Error" , "UI_ARG_OUT_OF_LIMIT" , OPT )
					return [1,0,0]
			except ValueError:
				try:
					#Is not an integer, could be a string repr
					ludes[i] =wmsui_api.states_codes.index(lud.capitalize())
				except ValueError:
					errMsg('Error', "UI_ARG_MISMATCH" , OPT)
					return [1,0,0]
			i+=1
		OPT= "--exclude"
	return 0 , includes ,excludes









############################################
# I PART: INIZIALIZING VARIABLES AND CHECKS
############################################
#initialize some usefull variable

json = False;

sys_exit =0
prgname="glite-wms-job-status"
wmsui_utils.err_log_clean(prgname)
wmsui_checks.check_prefix()
MSG_STATUS="=status="
MSG_EXCLUDE="=exclude="
error_message= wmsui_utils.createErrMsg( prgname , "job Id(s)",["help","version","@","all", "=input$","verbosity=","from=","to=",\
"=config$" ,"user-tag=", MSG_STATUS , MSG_EXCLUDE, "vo=","=output$","noint","nonodes" , "debug", "logfile$","json"])
argv=sys.argv
wmsui_checks.check_noint(sys.argv)


#=================================
#   Option check
#=================================
if (len(argv) < 2):
   wmsui_utils.print_help(error_message)
   exit(1)

err, options,values,extra = wmsui_checks.checkOpt(argv[1:] , "i:c:o:v:s:e:" ,["help","version","all", "input=","verbosity=", \
 "from=","to=","config=" ,"user-tag=", "status=","exclude=","vo=","output=","noint","nonodes" , "debug" , "logfile=","json"] )

if    ("--json" in options):
	json = True;

if    ("--help" in options):
   print "\n" + prgname +" full help"
   wmsui_utils.printFullHelp(error_message, wmsui_checks.info.noint)
   exit(0)
elif    ("--version" in options):
   print "Job Submission User Interface version " + wmsui_utils.info.version
   exit(0)
elif err:
   wmsui_utils.print_help(error_message)
   exit(1)
#Checking option syntax
"""
 -input/jobId sintax:
"""
ext= (len(extra) >0)

res=(   "--vo" in options  or "--all" in options  or  "--from" in options  or  "--to" in options or "--user-tag" in options  \
 or "-s" in options   or "-e" in options \
 or "--status" in options   or "--exclude" in options )\
 + ext + ( ("-i" in options) or ("--input" in options) )

if res == 0:
   #no input/job/all specified
   wmsui_utils.print_help(error_message)
   exit(1)
#Valued Option check:
noNodes = ("--nonodes"   in options)
try:
  inFile    = wmsui_utils.findVal( ["--input"  , "-i" ], options, values)
  outFile   = wmsui_utils.findVal(["--output" , "-o" ], options, values)
  gname    = wmsui_utils.findVal(["--config" , "-c" ], options, values)
  virtualOrg = wmsui_utils.findVal(["--vo" ], options, values)
  logpath = wmsui_utils.findVal(  ["--logfile"], options, values)
  level = wmsui_utils.findVal(["--verbosity", "-v"], options, values)
  fromT=  wmsui_utils.findVal(  ["--from"], options, values)
  toT=  wmsui_utils.findVal(  ["--to"], options, values)
  userTags = wmsui_utils.findVal(["--user-tag"], options, values, 1)
  includes = wmsui_utils.findVal(["--status", "-s"], options, values, 1)
  excludes = wmsui_utils.findVal(["--exclude","-e"], options, values, 1)
except SyntaxError,rep:
  errMsg('Error','UI_REPEATED_OPT',rep[0])
  wmsui_utils.print_help(error_message)
  exit(1)
  
# UI Configuration file Check
voName = wmsui_checks.checkConf (gname, virtualOrg, logpath)

err ,includes , excludes = checkExclude (includes , excludes)
if err:
     wmsui_utils.print_help(error_message)
     exit(1)

if level:
   try:
     level = int(level)
   except:
     errMsg('Error','UI_ARG_MISMATCH', level)
     wmsui_utils.print_help(error_message)
     exit(1)
   if (level >3):
     errMsg('Error','UI_ARG_OUT_OF_LIMIT', level)
     wmsui_utils.print_help(error_message)
     exit(1)
else:
   level = wmsui_utils.info.confAd.getIntValue ("DefaultStatusLevel")
   if level:
     try:
       level = int( level[0] )
     except:
       level=1
   else:
     level = 1

try:
	fromT , toT = wmsui_checks.checkFromTo (fromT , toT)
except:
	wmsui_utils.print_help(error_message)
	wmsui_utils.exit(1)

#=================================
#  USER TAGS
#=================================
uTags ={}
if userTags:
	try:
		for tag in userTags:
			attr , value = tag.split("=")
			if uTags.has_key(attr):
				errMsg('Error','UI_REPEATED_OPT',"--user-tag ("+attr +")" )
				wmsui_utils.print_help(error_message)
				exit(1)
			uTags[attr]=value
	except ValueError:
		errMsg('Error','UI_ARG_MISMATCH', "--user-tag")
		wmsui_utils.print_help(error_message)
		exit(1)

#=================================
#   jobID check
#=================================
if json == True:
	print "{ \"result\": \"success\"",
	
jobs= []

if extra:
	jobs = wmsui_api.getJobIdfromList ( json, extra )
	if len (jobs) != len(extra):
		sys_exit= -1
elif inFile :
	sys_exit , jobs, strjobs =wmsui_api.getJobIdfromFile( json, inFile )
	if sys_exit and jobs and (not wmsui_utils.info.noint):
		answ=wmsui_utils.questionYN("Do you wish to continue?")
		if not answ:
			print "bye"
			exit(1)
	if jobs and (not wmsui_utils.info.noint):
		jobs = wmsui_api.selectJobId( jobs, strjobs)

if not jobs:
	if sys_exit:
		# Unable to parse /find specified JobId
		if json == False:
			errMsg('Error','UI_WRONG_JOBID_ALL')
		else:
			print "}"
		exit(1)
	
#Define the error/warning message:
em="Error"

# check -output option
TBremoved = 0
if (outFile):
   err,outFile,TBremoved=wmsui_checks.check_outFile(outFile)
   if err or (not outFile):
      exit(err)
      
# Check if an output file has been specified and if it already exists
if outFile and TBremoved:
	# The file has to be removed
	os.remove(outFile)
	      
#Check proxy
if wmsui_checks.check_proxy():
   exit(1)

atLeastOneSuccess = 0
st = 0

#=================================
#   --all check
#=================================
if "--all" in options:
	issuer = wmsui_utils.info.issuer
else:
	issuer = ""

# Initialise the output message
message = ""

# Check if LB Query has been requested
LBapproach = includes or excludes or userTags or issuer or fromT or toT

# Retrieve the results according to the parameters
if LBapproach:

	print "\n*** LB APPROACH\n"

	# Query all the status
	statesArray = wmsui_api.queryStates(jobs, voName, includes, excludes, uTags, issuer, fromT, toT, level)

	if statesArray:
		# If this flag is set to 1 then the query might haven't found any results (but nevertheless no exception raised)
		atLeastOneSuccess = 1
		
		for job in jobs:
			#print "**** CHECKING JOB [" + job.jobid + "]"
			if job.jobid in statesArray:
				wmsui_utils.print_message(False, outFile, statesArray[job.jobid].printStatus(json, noNodes))
				st+=1
			else:	
				wmsui_utils.print_message(False, wmsui_utils.info.logFile, "Warning: no matching information for job id: " + job.jobid)
			

else:

#	//print "\n*** NO LB APPROACH\n" 

	# Set the error level to warning in case of more than one job
	if len (jobs)>1:
		em="Warning"

	# Get the status for all the Job ID
#	if json == True:
#		print "{ \"result\": \"success\", ",
		
	messageList = list()
		
	for jobid in jobs:
		#print "**** CHECKING JOB [" + jobid.jobid + "]"
		p = re.compile('^https://.+:[0-9]+/.+');
		m = p.match(jobid.jobid)
		if not m:
			#print "DONT MATCH!!!"
			messageList.append("\"" + jobid.jobid + "\": \"JOBID CONTAINS WRONG FORMAT: SHOULD BE https://<host>:<tcpport>/<ID>\"" )
			pass
		else:
			#print "GETTING STATUS..."
			dbgMsg ("Job::getStatus" , jobid.jobid, level)
			
			apiMsg = ""
			
			try:
				# Get the status of the current Job
				jobStatus = wmsui_api.getStatus(jobid, level)
				
				# Check if a status has been found
				if jobStatus:
					# Print the Status
				        #wmsui_utils.print_message(json, outFile, jobStatus.printStatus(json, noNodes))
			                messageList.append( jobStatus.printStatus(json, noNodes) )
				
				atLeastOneSuccess = 1
				st+=1
				
			except Exception, apiMsg:
				# Print the error message on log file
                                #wmsui_utils.print_message(json, wmsui_utils.info.logFile ,  "\n")
			
				if json == True:
					errmex = apiMsg.args[0].lower()
					print "\n\n********** errmex=["+errmex+"]\n\n"
					if errmex.find("no matching jobs found") > -1:
						messageList.append( "\"" + jobid.jobid + "\": \"JOB NOT FOUND\"" )
					if errmex.find("no route to host") > -1:
						messageList.append( "\"" + jobid.jobid + "\": \"JOBID CONTAINS WRONG ENDPOINT OR ENDPOINT CANNOT BE CONTACTED\"" )
					if errmex.find("connection timed out") > -1:
						messageList.append( "\"" + jobid.jobid + "\": \"JOBID CONTAINS WRONG ENDPOINT OR ENDPOINT CANNOT BE CONTACTED (CONNECTION TIMEOUT)\"" )
						
					if errmex.find("connection refused") > -1:
						messageList.append( "\"" + jobid.jobid + "\": \"JOBID CONTAINS WRONG ENDPOINT OR ENDPOINT CANNOT BE CONTACTED (CONNECTION REFUSED)\"" )
								
					if errmex.find("unknown host") > -1:
						messageList.append( "\"" + jobid.jobid + "\": \"JOBID CONTAINS UNKNOWN ENDPOINT\"" )
						
					if errmex.find("jobID is not in a valid format") != -1:
						messageList.append( "\"" + jobid.jobid + "\": \"JOBID FORMAT NOT VALID\"" )
					if errmex.find("bad argument") != -1:
						messageList.append( "\"" + jobid.jobid + "\": \"BAD ARGUMENT\"" )
											
				# Show on screen the error
				if json == False:
					pieces = apiMsg[0].split('\n')
					print "*** Warning: " + pieces[0] + "\n"
					cause = pieces[1]
					print cause.split(": ")[2] + " - " + cause.split(": ")[3] + "\n\n"
                                        #errMsg ( em , "API_NATIVE_ERROR" , "Job:getStatus"  , apiMsg.args[0] )

				# Set the exit code
				if json == False:
					sys_exit= -1

	#wmsui_utils.print_message(json, outFile, ",".join( messageList ) )

	if json == True:
		wmsui_utils.print_message(json, outFile, ", " + ", ".join( messageList ) )
		print " }"
	else:
		wmsui_utils.print_message(json, outFile, "\n".join( messageList ) )
		
if level==0 and atLeastOneSuccess :
	if json == False:
		wmsui_utils.print_message(json, outFile,"==========================================================================\n")

#Final error Check
if not st:
	#No information got
	if jobs:
		# JOBID SPECIFICATED
		if len(jobs) !=1:
			#not only 1 JobId: Warning Message only printed so far. print the last message
			print ""#errMsg('Error','LB_API_OPEN_ALL')
	elif  atLeastOneSuccess:
		#  query on LB server performed but no job found
		print ""#errMsg("Error","UI_NO_JOB_FOUND")
	else:
		# All LB Queries went wrong (only warning so far)
		print ""#errMsg('Error','LB_API_OPEN_ALL')
	exit(1)
else:
	if outFile:
		message='======================== glite-wms-job-status success ========================\n'
		message=message + " Bookkeeping information has been found and stored in the file:\n"
		message=message+ " "+ outFile
		message=message+'\n==========================================================================\n'
		wmsui_utils.print_message(False, wmsui_utils.info.logFile,message)
	exit(sys_exit)




