#!/usr/bin/env python3


import os
from base64 import b64decode

from flask import Flask, jsonify, request, abort, Response, make_response
from nacl import signing
from nacl import encoding

class SVCNode:
    """
    info on a service node
    """
    def __init__(self):
        self._seed = os.urandom(32)
        self._ed25519_secret = signing.SigningKey(self._seed)

    def seed(self):
        """
        return hex seed
        """
        return self._ed25519_secret.encode(encoding.HexEncoder).decode('ascii') + self.pubkey()

    def pubkey(self):
        """
        make hex public key
        """
        return self._ed25519_secret.verify_key.encode(encoding.HexEncoder).decode('ascii')

    def toJson(self):
        """
        make the snode a json object for jsonrpc
        """
        return {'pubkey_ed25519': self.pubkey(), 'active': True, 'funded': True}

class MockServer:

    def __init__(self, numServiceNodes):
        self.app = Flask('lokid-rpc-mock')
        #self.app.config['SECRET_KEY'] = os.urandom(16)
        # populate service nodes
        self._serviceNodes = dict()
        for n in range(numServiceNodes):
            self.makeSNode("svc-%03d" % n)

        self._handlers = {
            'lokinet_ping': self._lokinet_ping,
            'get_n_service_nodes' : self._get_n_service_nodes,
            'get_service_node_privkey' : self._get_service_node_privkey
        }
        #digest = HTTPDigestAuth(realm='lokid')
    
        @self.app.route('/json_rpc', methods=["POST"])
        def _jsonRPC():
            j = request.get_json()
            method = j['method']
            snode = None
            if 'authorization' in request.headers:
                user = b64decode(request.headers['authorization'][6:].encode('ascii')).decode('ascii').split(':')[0]
                self.app.logger.error(user)
                if len(user) > 0:
                    snode = self._serviceNodes[user]
            result = self._handlers[method](snode)
            if result:
                resp = {'jsonrpc': '2.0', 'id': j['id'], 'result': result}
                return jsonify(resp)
            else:
                r = make_response('nope', 401)
                r.headers['www-authenticate'] = 'basic'
                return r
        def after(req):
            req.content_type = "application/json"
            return req
        self.app.after_request(after)

    def _get_n_service_nodes(self, our_snode):
        return {
            'block_hash' : 'mock',
            'service_node_states' : self.getSNodeList()
        }
    
    def _get_service_node_privkey(self, our_snode):
        if our_snode is None:
            return None
        return {
            'service_node_ed25519_privkey': our_snode.seed()
        }

    def _lokinet_ping(self, snode):
        return {
            'status' : "OK"
        }
    
    def run(self):
        """
        run mainloop and serve jsonrpc server
        """
        self.app.run()
    
    def makeSNode(self, name):
        """
        make service node entry
        """
        self._serviceNodes[name] = SVCNode()


    def getSNodeList(self):
        l = list()
        for name in self._serviceNodes:
            l.append(self._serviceNodes[name].toJson())
        return l
    

def main():
    import sys
    serv = MockServer(int(sys.argv[1]))
    serv.run()
    
if __name__ == '__main__':
    main()
