import sys, os, datetime, hashlib, hmac
from StringIO import StringIO
import gzip
import urllib
import urllib2
import json

def get_filters_2(**kwargs):
	filter_stack = []
	canonical_querystring = ""
	url_encoding = kwargs.get("url_encoding")  
	
	sources = kwargs.get("sources")
	if sources:
		source_string = "SourceId=" +  ",".join(sources)
		filter_stack.append(source_string)
	
	devices = kwargs.get("devices")
	if devices:
		device_string = "Device=" + ",".join(devices)
		filter_stack.append(device_string)
	
	priorities = kwargs.get("priorities")
	if priorities:
		priority_string = "Priority=" + ",".join(str(item) for item in priorities)
		filter_stack.append(priority_string)
		
	types =  kwargs.get("types") 
	if types:
		type_string = ("Type=" + ",".join(str(item) for item in types))
		filter_stack.append(type_string)

	time_from = kwargs.get("start")
	if time_from:
		time_from_string = "StartTimestamp=" + str(time_from)
		filter_stack.append(time_from_string)
	
	time_to = kwargs.get("end")
	if time_to:
		time_to_string = "EndTimestamp=" + str(time_to)
		filter_stack.append(time_to_string)
	
	duration =  kwargs.get("duration") 
	if duration:
		duration_string = "MinimumDuration=" + str(duration)
		filter_stack.append(duration_string)
	if filter_stack:
		if url_encoding:
			canonical_querystring += "Filter="
		for i, j in enumerate(filter_stack):
			if i == len(filter_stack)-1 and url_encoding == True:
				canonical_querystring += urllib.quote(j, "")
			elif i == len(filter_stack)-1:
				canonical_querystring += j
			elif url_encoding == True:
				canonical_querystring += urllib.quote(j  + "&", "")
			else:
				canonical_querystring += (j + "&")
	
	return canonical_querystring

def get_filters(**kwargs):
	#Build filter string, filters are passed as key word arguments into the function
	#Check if any of the filters have been passed means we need to add Filter=.
	#Each filter is then converted using the urllib_parse.
	canonical_querystring = ""
	sources = kwargs.get("sources")
	devices = kwargs.get("devices")
	priorities = kwargs.get("priorities")
	types =  kwargs.get("types") 
	time_from = kwargs.get("start")
	time_to = kwargs.get("end")
	duration =  kwargs.get("duration") 
	url_encoding =  kwargs.get("url_encoding")  
	filter_list = [sources, devices, priorities, types, time_from, time_to, duration]
	if any(filter_list):
		canonical_querystring = "Filter="
		if sources:
			source_string = ("SourceId=" + ",".join(sources))
			if url_encoding == True:
				canonical_querystring += urllib.quote(source_string + "&","") 
			else:
				canonical_querystring += source_string + "&"
		if devices:
			device_string = ("Device=" + ",".join(devices))
			if url_encoding == True:
				canonical_querystring += urllib.quote(device_string + "&","")
			else:
				canonical_querystring += device_string +"&"
		if priorities:
			priority_string = ("Priority=" + ",".join(str(item) for item in priorities))
			if url_encoding == True:
				canonical_querystring += urllib.quote(priority_string + "&", "")
			else:
				canonical_querystring += priority_string +"&"
		if types:
			type_string = ("Type=" + ",".join(str(item) for item in types))
			if url_encoding == True:
				canonical_querystring += urllib.quote(type_string + "&","")
			else:
				canonical_querystring += type_string +"&"
		if time_from:
			if url_encoding == True:
				canonical_querystring += urllib.quote("StartTimestamp=" + str(time_from) + "&","")
			else:
				canonical_querystring += "StartTimestamp=" + str(time_from) +"&"
		if time_to:
			if url_encoding == True:
				canonical_querystring += urllib.quote("EndTimestamp=" + str(time_to) + "&","")
			else:
				canonical_querystring += "EndTimestamp=" + str(time_to) +"&"
		if duration:
			if url_encoding == True:
				canonical_querystring += urllib.quote("MinimumDuration=" + str(duration) + "&","")
			else:
				canonical_querystring += "MinimumDuration=" + str(duration)  +"&"
		system.perspective.print("filtered string = " + canonical_querystring )
		canonical_querystring = canonical_querystring.rstrip("&")
	return canonical_querystring
	
def get_response(response):
	if response.info().get('Content-Encoding') == 'gzip':
	    buf = StringIO(response.read())
	    f = gzip.GzipFile(fileobj=buf)
	    data = f.read()
	    return (response.getcode(), data)
	else:
		buf = StringIO(response.read())
		return(response.getcode(), buf.read())

def build_url(credentials, **kwargs):
	# ************* REQUEST VALUES *************
	method = 'GET'
	service = 'lambda'

	# This is a lookup in secrets to a return the function url for the lambda that needs called. 
	# This allows beta and prod to be dynamically retrived. 
	whid = kwargs.get("fc")
	region =  kwargs.get("region")
	API_ID, STAGE, ACC_ID, FUNC_URL = AWS.secrets_manager.get_secret(str(whid), 'scada/api/endpoint')
	api_id = FUNC_URL
	host = "%s.%s-url.%s.on.aws" % (api_id, service, region)
	endpoint = "https://%s" % (host)
	
	
	# Key derivation functions. See:
	# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
	def sign(key, msg):
	    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
	
	def getSignatureKey(key, dateStamp, regionName, serviceName):
	    kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
	    kRegion = sign(kDate, regionName)
	    kService = sign(kRegion, serviceName)
	    kSigning = sign(kService, 'aws4_request')
	    return kSigning
	
	# Read AWS access key from env. variables or configuration file. Best practice is NOT
	# to embed credentials in code.
#	access_key = os.environ.get('AWS_ACCESS_KEY_ID')
#	access_key= 'ASIATVSVCYSV2JJJMDPP'
#	secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
#	secret_key= 'Hc0G/0eACBlgplGSBnfsB98Y6DPqwpvyb4nc1Rvs'
#	session_token = os.environ["AWS_SESSION_TOKEN"]
#	session_token= 'IQoJb3JpZ2luX2VjEJr//////////wEaCWV1LXdlc3QtMSJHMEUCIQCbrPQoj4OM0SXIo6QtcNAblnplgXfvSYIcA+k8xkXmZwIgN1Pi7Nyc66T8p0HkZSMmuW8pu1qPEVJii41YgYCuiBYqngIIo///////////ARAAGgwyNTI1MDc3Njc5NzkiDKGV69tLNcKNVcoeryryARkU2Lmnj0aa+ilLOrg35FIb81jvmj6bpPR3+5zJ3Wna+vOBgz6cqphyn28+Q8Ryw/lzM6gM0vWH+gV26CuQZtKd1U4ETo9eL9QuluLBqLnZYfT5q+F9hzJy3OQQl0c3VvwcaCjOPrMdbvWnJGEoEZTKe7Xm5v3ok3huJDgKLEIVlE6Z4c2kKNy/N/JfbxB5a33A2eaE9YaGj1V0cQgUFCCkn9uDq8W4TzOPZ3NgKAyj8RoBR6KAC8gEtWXFEwwZR3ZMwYIXryEepcU7HQSHpp66JAFm/X5+HNxRe7WUwTETAveYMNi5ssFzl3rneKh9+U37MPW58psGOp0B11BghSma0KZHgCfXqdsgfGyD7/sBEyYE9wdnzmi8fOpel5EDQoUoYilRSXod2E9wlaXj3h8S+dtBJjGVqsIbHEIrW7WKOEYELxoW4VSDw5hDjZaUuZ5fA3z59c4CEeAz3v5EA6NN6+ulEb7/4pbWF8s3fezNk9T73NpmKnjaMFukcBX8DofesZGJFpfGij2Sx4hQ3qlmG91uac8kMw=='
	access_key = credentials["AccessKey"]
	secret_key = credentials["SecretKey"] 
	session_token = credentials["SessionKey"]
	
	
	
	if access_key is None or secret_key is None:
	    system.perspective.print('No access key is available.')
	    sys.exit()
	
	# Create a date for headers and the credential string
	t = datetime.datetime.utcnow()
	amz_date = t.strftime('%Y%m%dT%H%M%SZ') # Format date as YYYYMMDD'T'HHMMSS'Z'
	datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope
	system.perspective.print("creating header")
	system.perspective.print("datestamp = " + str(datestamp) + " region = " + str(region) + "service = " + str(service))
	
	# ************* TASK 1: CREATE A CANONICAL REQUEST *************
	# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
	
	# Because almost all information is being passed in the query string,
	# the order of these steps is slightly different than examples that
	# use an authorization header.
	
	# Step 1: Define the verb (GET, POST, etc.)--already done.
	
	# Step 2: Create canonical URI--the part of the URI from domain to query 
	# string (use '/' if no path)
	fc = kwargs.get("fc")
	canonical_uri = "/history/%s" % (fc)
	
	# Step 3: Create the canonical headers and signed headers. Header names
	# must be trimmed and lowercase, and sorted in code point order from
	# low to high. Note trailing \n in canonical_headers.
	# signed_headers is the list of headers that are being included
	# as part of the signing process. For requests that use query strings,
	# only "host" is included in the signed headers.
	canonical_headers = 'host:' + host + '\n'
	signed_headers = 'host'
	
	# Match the algorithm to the hashing algorithm you use, either SHA-1 or
	# SHA-256 (recommended)
	algorithm = 'AWS4-HMAC-SHA256'
	
	credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
	
	# Step 4: Create the canonical query string. In this example, request
	# parameters are in the query string. Query string values must
	# be URL-encoded (space=%20). The parameters must be sorted by name.
	#canonical_querystring = 'Action=CreateUser&UserName=NewUser&Version=2010-05-08'
	#canonical_querystring = 'NextToken=' + urllib.parse.quote("1669217267.5230844/PLC09/T00049",'') + '&PageSize=50'
	#canonical_querystring = 'PageSize=50&PreviousToken=' + urllib.parse.quote('1669217267.5824845/PLC09/T00099','')
	canonical_querystring = ""
	#Build filter string, filters are passed as key word arguments int the function
	#Check if any of the filters have been passed means we need to add Filter=.
	#Each filter is then converted using the urllib_parse.
	#Including client id for timestream api.
	client_id = kwargs.get("client_id")
	if client_id:
		canonical_querystring += 'ClientId=' + client_id + '&'
	PAGE_SIZE = "200"
	filters= kwargs.get("filters","")
	if filters != "":
		canonical_querystring += filters + "&"
	
	next_token = kwargs.get("next_token")
	
	previous_token = kwargs.get("previous_token")
	if next_token != None:
		canonical_querystring += 'NextToken=' + urllib.quote(next_token,'') + '&'
		system.perspective.print("created string " + canonical_querystring)
	
	if previous_token != None:
		canonical_querystring += 'PreviousToken=' + urllib.quote(previous_token,'') + '&'
	
	else:
		canonical_querystring += 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
	canonical_querystring += '&X-Amz-Credential=' + urllib.quote_plus(access_key + '/' + credential_scope)
	canonical_querystring += '&X-Amz-Date=' + amz_date
	#canonical_querystring += '&X-Amz-Expires=30'
	canonical_querystring += "&X-Amz-Security-Token=" + urllib.quote_plus(session_token)
	canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
	
	
	# Step 5: Create payload hash. For GET requests, the payload is an
	# empty string ("").
	payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
	
	# Step 6: Combine elements to create canonical request
	canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
	
	
	# ************* TASK 2: CREATE THE STRING TO SIGN*************
	string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
	
	# ************* TASK 3: CALCULATE THE SIGNATURE *************
	# Create the signing key
	signing_key = getSignatureKey(secret_key, datestamp, region, service)
	
	# Sign the string_to_sign using the signing_key
	signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
	
	
	# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
	# The auth information can be either in a query string
	# value or in a header named Authorization. This code shows how to put
	# everything into a query string.
	canonical_querystring += '&X-Amz-Signature=' + signature
	
	
	# ************* SEND THE REQUEST *************
	# The 'host' header is added automatically by the Python 'request' lib. But it
	# must exist as a header in the request.
	request_url = endpoint + canonical_uri + "?" + canonical_querystring
	
	system.perspective.print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
	system.perspective.print('Request URL = ' + request_url)
#	r = requests.get(request_url)
	request = urllib2.Request(request_url)
	request.add_header('Accept-encoding', 'gzip')
	try:
		response = urllib2.urlopen(request)
	except urllib2.HTTPError as e:
		return(e.code, None)
	except urllib2.URLError as e:
		return(e.reason, None)
	return get_response(response)
	
