#!/usr/bin/python

from hashlib import sha1

import base64
import getopt
import hashlib
import hmac
import json
import os
import re
import requests
import subprocess
import sys
import time

def Usage():
	print 'ice-register [OPTIONS]'
	print '   --url=[URL]             Target to register with'
	print '   --access=[KEY]          Access key'
	print '   --dev=[KEY]             Dev key'
	print '   --shared=[KEY]          Shared key'
	print '   --protocol=[http]       Connection protocol'
	print '   --help                  You are here'

def getValueFromRegistrationXml(pattern, name):
  if os.path.isfile("/usr/bin/raven/registration.xml"):
    file = open("/usr/bin/raven/registration.xml")
    pattern = re.compile(pattern)
    for l in file:
      match = pattern.search(l)
      if (match):
        print 'using ' + name + ' from registration.xml'
        return  match.group(1)
  return ''

def fwOutputBlank(processOutput):
    return processOutput.startswith('#') or processOutput == ''

def main(argv):

  url = '192.168.3.89:8090'
  protocol = 'http'
  try:
    opts, args = getopt.getopt(sys.argv[1:],"hu:a:d:s:p:", ["help", "url=", "access=", "dev=", "shared=", "protocol=","host="])
  except getopt.GetoptError as err:
    print str(err)
    Usage()
    sys.exit(2)
  for opt, arg in opts:
    if opt in ("-h", "--help"):
       Usage()
       sys.exit()
    elif opt in ("-u", "--url"):
	   url = arg;
	   print "Setting URL: " + url
    elif opt in ("-a", "--access"):
       access_key = arg;
    elif opt in ("-d", "--dev"):
       dev_key = arg;
    elif opt in ("-s", "--shared"):
       shared_secret = arg;
    elif opt in ("-p", "--protocol"):
       protocol = arg;
    elif opt in ("--host"):
       host = arg;
    else:
      Usage()
      sys.exit(2)
  device_data = {}

  access_key="97336175-AC84-C0C9-04CE-B35AF9DDF9C1"
  dev_key="JuNPcVn7lWz108brgcI1BkGG0LKr9SC+P1KsFYak"
  shared_secret="P3R6VemUanF4VRoUjpK9PskjCTFwRiDVgPaFAAUn"
  
  p = subprocess.Popen(['/sbin/fw_printenv', 'rvn_as_sn'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  out, err = p.communicate()
  rvn_as_sn=out
  if fwOutputBlank(rvn_as_sn):
    rvn_as_sn = getValueFromRegistrationXml("<SerialNumber>(.*)</SerialNumber>", "assembly serial number")
  else:
    print 'using assembly serial number from uboot'
    rvn_as_sn=rvn_as_sn.strip()[10:]
  if (len(rvn_as_sn) < 4):
    sys.exit('INVALID SERIAL NUMBER:' + rvn_as_sn)
  print 'serial_number=' + rvn_as_sn
  device_data['serial_number'] = rvn_as_sn

  p = subprocess.Popen(['/sbin/fw_printenv', 'rvn_uuid'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  out, err = p.communicate()
  rvn_uuid=out
  rvn_uuid=rvn_uuid.strip()[9:]
  print 'uuid=' + rvn_uuid
  device_data['uuid'] = rvn_uuid
  device_data['external_device_id'] = rvn_uuid

  p = subprocess.Popen(['/sbin/fw_printenv', 'rvn_as_bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  out, err = p.communicate()
  rvn_as_bc=out
  if fwOutputBlank(rvn_as_bc):
    rvn_as_bc = getValueFromRegistrationXml("<Barcode>(.*)</Barcode>", "assembly barcode")
  else:
    print 'using bar code from uboot'
    rvn_as_bc=rvn_as_bc.strip()[10:]
  if (len(rvn_as_bc) < 7):
    sys.exit('INVALID BAR CODE:' + rvn_as_bc)
  print 'bar_code=' + rvn_as_bc
  device_data['bar_code'] = rvn_as_bc

  p = subprocess.Popen(['/sbin/fw_printenv', 'rvn_as_fpn'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  out, err = p.communicate()
  rvn_as_pn=out
  if fwOutputBlank(rvn_as_pn):
    rvn_as_pn = getValueFromRegistrationXml("<PartNumber>(.*)<\/PartNumber>", "assembly part number")
  else:
    print 'using assembly part number from uboot'
    rvn_as_pn=rvn_as_pn.strip()[11:]
  if (len(rvn_as_pn) < 4) or (rvn_as_pn == '0630173000'):
    sys.exit("INVALID PART NUMBER:" + rvn_as_pn)
  if rvn_as_pn[0] == '0':
    rvn_as_pn = '1' + rvn_as_pn
  print "part_number=" + rvn_as_pn
  device_data['part_number'] = rvn_as_pn

  p = subprocess.Popen(['/sbin/fw_printenv', 'rvn_sw_pn'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  out, err = p.communicate()
  rvn_sw_pn=out
  if fwOutputBlank(rvn_sw_pn):
    rvn_sw_pn = getValueFromRegistrationXml("<SoftwareFile>(.*)<\/SoftwareFile>", "software part number")
  else:
    print 'Using software part number from uboot'
    rvn_sw_pn=rvn_sw_pn.strip()[10:]
  device_data['software_part_number'] = rvn_sw_pn
  print "software_part_number=" + device_data["software_part_number"]

  if os.path.isfile("/etc/raven/cell/IMEI"):
    file = open("/etc/raven/cell/IMEI", "r")
    cellular_imei=file.read()
    print "imei=" + cellular_imei
    device_data['imei'] = cellular_imei

  if os.path.isfile("/etc/raven/cell/SIMID"):
    file = open("/etc/raven/cell/SIMID", "r")
    cellular_simid=file.read()
    print "simid=" + cellular_simid
    device_data['sim'] = cellular_simid

  if os.path.isfile("/etc/raven/platform"):
    file = open("/etc/raven/platform", "r")
    raven_platform = file.read().strip()
    print "platform=" + raven_platform
    device_data['type'] = raven_platform

  try:
    RegisterPinehurst(url, protocol, access_key, dev_key, shared_secret, device_data)
  finally:
    if VerifyRegistration(url, protocol, access_key, dev_key, shared_secret, device_data):
      print "Registration-Status: Success"
      os._exit(0)
    print "Unexpected error:", sys.exc_info()[0]
    print "Registration-Status:Failure"
    sys.exit(3)

def calculate_signature(
        shared_secret,
        method,
        url,
        host,
        api_key,
        access_key,
        timestamp
        ):
    sig_block = "{}\r\n{}\r\n{}\r\n{}\r\n{}\r\n{}\r\n".format(
            method.upper(),
            host,
            url.lower(),
            timestamp,
            api_key,
            access_key)
    print "\n\n -- sig block -- \n" + sig_block + "\n\n"
    decoded_secret = base64.b64decode(shared_secret)
    hashed = hmac.new(decoded_secret, sig_block, sha1)
    sig =  hashed.digest().encode("base64").rstrip('\n')
    return sig

def GetFieldComputers(host, protocol, access_key, dev_key, shared_secret):
    path = '/fieldcomputers'
    stamp = str(int(time.time()))
    signature = calculate_signature(shared_secret, 'GET', path, host, dev_key, access_key, stamp)
    headers = {
            'X-SS-APIKEY' : dev_key,
            'X-SS-AccessKey' : access_key,
            'X-SS-TimeStamp' : stamp,
            'X-SS-Signature' : signature,
            'Accept' : 'application/json'
            }
    print headers
    r = requests.get(protocol + '://' + url + path, headers=headers)
    return r.content

def GetHardware(host, protocol, access_key, dev_key, shared_secret):
    path = '/hardware'
    stamp = str(int(time.time()))
    signature = calculate_signature(shared_secret, 'GET', path, host, dev_key, access_key, stamp)
    headers = {
            'X-SS-APIKEY' : dev_key,
            'X-SS-AccessKey' : access_key,
            'X-SS-TimeStamp' : stamp,
            'X-SS-Signature' : signature,
            'Accept' : 'application/json'
            }
    r = requests.get(protocol + '://' + host + path, headers=headers)
    return r.content

def VerifyRegistration(url, protocol, access_key, dev_key, shared_secret, device_data):
    path = '/hardware/uuid/' + device_data['uuid']
    stamp = str(int(time.time()))
    signature = calculate_signature(shared_secret, 'GET', path, url, dev_key, access_key, stamp)
    headers = {
            'X-SS-APIKEY' : dev_key,
            'X-SS-AccessKey' : access_key,
            'X-SS-TimeStamp' : stamp,
            'X-SS-Signature' : signature,
            'Accept' : 'application/json'
    }
    json_data = json.dumps(device_data)
    print "Json verification data is: {}".format(json_data)
    r = requests.get(protocol + '://' + url + path, data=json.dumps(device_data), headers=headers)
    print "Response is:" + r.content
    vd = json.loads(r.content)
    return (
        printCompare('serial_number',vd, device_data) and
        printCompare('part_number', vd, device_data) and
        printCompare('bar_code', vd, device_data) and
        printCompare('external_device_id', vd, device_data, 'uuid')
        )
        
def printCompare(key, data1, data2, altKey=''):
    val1 = data1[key]
    val2 = data2[key] if len(altKey) == 0 else data2[altKey]
    if val1 == val2:
        print("{key} data is correct".format(key=key))
        return True
    print("{key} data incorrect {data1}:{data2}".format(key=key, data1=val1, data2=val2))
    return False

def RegisterPinehurst(url, protocol, access_key, dev_key, shared_secret, device_data):
    path = '/hardware'
    stamp = str(int(time.time()))
    signature = calculate_signature(shared_secret, 'POST', path, url, dev_key, access_key, stamp)
    headers = {
            'X-SS-APIKEY' : dev_key,
            'X-SS-AccessKey' : access_key,
            'X-SS-TimeStamp' : stamp,
            'X-SS-Signature' : signature,
            'Accept' : 'application/json'
    }
    json_data = json.dumps(device_data)
    print "Json data is: {}".format(json_data)

    r = requests.post(protocol + '://' + url + path, data=json.dumps(device_data), headers=headers)
    try:
        r.raise_for_status()
    except requests.exceptions.HTTPError as err:
        print r.content
        raise
    return r.content

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