# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2014 Regents of the University of California.
# Author: Teng Liang <philoliang2011@gmail.com>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# A copy of the GNU General Public License is in the file COPYING.


import time
import json
from pyndn import Name, Face, Interest, Data
from pyndn.key_locator import KeyLocator, KeyLocatorType
from hmac_helper import HmacHelper 

from pyndn.security import KeyChain
from base_node import BaseNode
from pyndn.security import SecurityException
from pyndn.util import Blob


def dump(*list):
    result = ""
    for element in list:
        result += (element if type(element) is str else repr(element)) + " "
    print(result)

class Controller(BaseNode):
    def __init__(self,configFileName):
        super(Controller, self).__init__(configFileName=configFileName)
        self._responseCount = 0
        self._symmetricKey = "symmetricKeyForBootstrapping"
        self._prefix = "/home"
        self._identity = "/home/controller/id999"
        self._hmacHelper = HmacHelper(self._symmetricKey)

    def setFace(self,face):
        self.face = face

    def onInterest(self, prefix, interest, transport, registeredPrefixId):
        self._responseCount += 1
        interestName = interest.getName()
        dump("received interest : ",interestName.toUri())

        #for bootstrap interest
        #if(interestName.toUri().startswith(self._bootstrapPrefix) and interest.getKeyLocator().getKeyData().toRawStr() == self._symmetricKey):
        if(interestName.toUri().startswith(self._bootstrapPrefix) and self._hmacHelper.verifyInterest(interest)):
            dump("Reveived bootstrap interest")
	    self.onBootstrapInterest(prefix, interest, transport, registeredPrefixId)   
        
        elif ("KEY" in interestName.toUri() and "ID-CERT" in interestName.toUri()):
            dump("Reveived certificate request interest")
            self.onCertificateRequest(prefix, interest, transport, registeredPrefixId)

    def onBootstrapInterest(self, prefix, interest, transport, registeredPrefixId):
        if (self._hmacHelper.verifyInterest(interest)):
            self.log.info("Bootstrap interest verified")
            interestName = interest.getName()
            deviceParameters = json.loads(interestName.get(3).getValue().toRawStr())
            deviceNewIdentity = Name("/home")
                
            #create new identity for device
            deviceNewIdentity.append(deviceParameters["category"])
            deviceNewIdentity.append(deviceParameters["id"])
                
            #generate content
            content = {}
            content["deviceNewIdentity"] = deviceNewIdentity.toUri()
            content["controllerIdentity"] = self._identity

            #get public key of controller
            pKeyName = self._identityManager.getDefaultKeyNameForIdentity(self._identityManager.getDefaultIdentity())
            pKey = self._identityManager.getPublicKey(pKeyName)

            pKeyInfo = content["controllerPublicKey"] = {}
            pKeyInfo["keyName"] = pKeyName.toUri()
            pKeyInfo["keyType"] = pKey.getKeyType()
            pKeyInfo["publicKeyDer"] = pKey.getKeyDer().toRawStr()
            dump("Sent content : ",content)
                  
            #TODO generate signature for data
                
            #generate data package
            data = Data(interestName)
            data.setContent(json.dumps(content,encoding="latin-1"))
            #data.setSignature(signature)
	    self._hmacHelper.signData(data)

            #encodedData = data.wireEncode()
            #transport.send(encodedData.toBuffer())
            self.sendData(data,transport,sign=False)
        else: 
            self.log.info("Bootstrap interest not verified")
        
    


    def onCertificateRequest(self, prefix, interest, transport, registeredPrefixId):
        if (self._hmacHelper.verifyInterest(interest)):
            self.log.info("certificate request interest verified")
            interestName = interest.getName()
            dump("interest name : ",interestName)
            
            keyName = interestName[:3]
            keyId = interestName.get(4)
            keyName.append(keyId)
            keyInfo = json.loads(interestName.get(5).getValue().toRawStr(),encoding="latin-1")
            keyType = keyInfo['keyType']
            keyDer = Blob().fromRawStr(keyInfo['keyDer'])

            #dump("keyname: ",keyName)
            dump("keyType ",keyInfo['keyType'])
            dump("keyDer string",keyInfo['keyDer'])
            dump("keyDer",keyDer)

            #device and controller are on one mechine, so it needs to be done.
            self._identityManager.setDefaultIdentity(Name(self._identity))
            try:
                self._identityStorage.addKey(keyName, keyType, keyDer)
            except SecurityException:
                dump("The public key for device already exists ")

            signedCertificate = self._identityManager._generateCertificateForKey(keyName)
            self._keyChain.sign(signedCertificate, self._identityManager.getDefaultCertificateName())
            self._identityManager.addCertificate(signedCertificate)
            #self._hmacHelper.signData()

            #encodedData = signedCertificate.wireEncode()
            #transport.send(encodedData.toBuffer())
	    self.sendData(signedCertificate,transport,sign=False)

	    self.log.info("Certificate sent back : {}".format(signedCertificate.__str__))
	    print(signedCertificate)
        else:
            self.log.info("certificate request interest not verified")
        


    def onRegisterFailed(self, prefix):
        self._responseCount += 1
        dump("Register failed for prefix", prefix.toUri())

    def beforeLoopStart(self):
        identityName = Name(self._identity)
        
        defaultIdentityExists = True
        try:
            defaultIdentityName = self._identityManager.getDefaultIdentity()
        except:
            defaultIdentityExists = False

        if not defaultIdentityExists or self._identityManager.getDefaultIdentity() != identityName:
            #make one
            dump("Create identity and certificate for identity name: ",identityName)
            self._keyChain.createIdentityAndCertificate(identityName)
       	    self._identityManager.setDefaultIdentity(identityName)

	self.face.setCommandSigningInfo(self._keyChain, self.getDefaultCertificateName())
        self.face.registerPrefix(self._prefix, self.onInterest, self.onRegisterFailed)
        
        


if __name__ == '__main__':

    controller = Controller("default.conf")
    controller.start()
    #controller.beforeLoopStart()
    

    #face = Face()
    #controller.setFace(face)

    #face.setCommandSigningInfo(controller._keyChain, controller.getDefaultCertificateName())
    #face.registerPrefix(controller._prefix, controller.onInterest, controller.onRegisterFailed)
    #dump("Register prefix : ",controller._prefix)
    #while True:
    #    face.processEvents()
#	time.sleep(0.05)

 #   face.shutdown()




    


