# Path: pyledger/server/handlers.py
# def handle_request(payload: bytes):
#     """
#     Handle a single request
# 
#     :param payload: Serialized PyledgerRequest message
#     :return:
#     """
#     handler = Handler()
#     message = PyledgerRequest()
#     response = PyledgerResponse()
# 
#     try:
#         message.ParseFromString(payload)
#     except DecodeError:
#         response.successful = False
#         response.data = b'Message not properly formatted'
#         return response.SerializeToString()
# 
#     if message.request not in handler_methods(handler):
#         response.successful = False
#         response.data = 'Request type {} not available'.format(message.request).encode()
#         return response.SerializeToString()
# 
#     else:
#         # Handle authentication
#         if message.request in permissions_registry:
#             user = User.from_name(message.user)
#             permission_required = permissions_registry[message.request]
# 
#             if not user.check_password(message.password):
#                 response.successful = False
#                 response.data = b'Wrong user and/or password'
#                 return response.SerializeToString()
# 
#             if user.get_permissions().value > permission_required.value:
#                 response.successful = False
#                 response.data = b'Not enough permissions'
#                 return response.SerializeToString()
# 
#             session = Session.from_key(message.session_key)
# 
#             if not session:
#                 response.successful = False
#                 response.data = b'Session not available'
#                 return response.SerializeToString()
# 
#             if not session.user == user:
#                 response.successful = False
#                 response.data = b'Session not owned by this user'
#                 return response.SerializeToString()
# 
#             if session.until < datetime.datetime.now():
#                 response.successful = False
#                 response.data = b'Session expired, restart your client'
#                 return response.SerializeToString()
# 
#         # Select the function from the handler
#         try:
#             print('Handling message', message)
#             successful, result = getattr(handler, message.request)(message)
#         except Exception as exc:
#             successful = False
#             result = b'Exception in user function: ' + repr(exc).encode('utf-8')
# 
#         response.successful = successful
#         response.data = result
#         return response.SerializeToString()
# 
# Path: pyledger/server/contract.py
# def register_contract(contract, description=''):
#     """
#     Register a contract and make it
#     :param contract:
#     :param description:
#     :return:
#     """
#     global contract_registry
# 
#     if contract.__class__.__name__ in contract_registry:
#         raise ValueError('A contract with the same name already registered')
#     else:
#         contract_registry[contract.__class__.__name__] = contract
# 
#     db_contract = Contract()
#     db_contract.name = contract.__class__.__name__
#     db_contract.created = datetime.datetime.now()
#     db_contract.description = description
# 
#     first_status = Status()
#     first_status.contract = db_contract
#     first_status.when = datetime.datetime.now()
#     first_status.attributes = status(contract).dump()
#     # Genesis key is the name of the contract
#     first_status.key = contract.__class__.__name__.encode('utf-8')
# 
#     DB.session.add(db_contract)
#     DB.session.add(first_status)
#     DB.session.commit()
# 
# class SimpleContract(BaseContract):
#     """
#     Contract that uses SimpleStatus for serialization.
# 
#     The goal of this class is to make a contact feel just like a Python class.
#     """
#     _status_class = SimpleStatus
# 
# Path: pyledger/server/db.py
# DB = Handler()
# 
# Path: pyledger/server/auth.py
# def create_master(password):
# def create_user(name, password):
# def allow(permission):
#     def decorator(func):
# def method_allow(permission):
#     def decorator(func):


from autobahn.asyncio.websocket import WebSocketServerProtocol, \
    WebSocketServerFactory
from pyledger.server.handlers import handle_request
from pyledger.server.contract import register_contract, SimpleContract
from pyledger.server.db import DB
from pyledger.server.auth import Permissions, method_allow
import asyncio
            print("unregistered client {}".format(client.peer))
            self.clients.remove(client)

    def broadcast(self, msg):
        print("broadcasting message '{}' ..".format(msg))
        for c in self.clients:
            c.sendMessage(msg, True)
            print("message sent to {}".format(c.peer))


def run_server(address="ws://127.0.0.1:9000"):
        factory = BroadcastServerFactory(address)
        factory.protocol = Protocol
        server = loop.create_server(factory,
                                    '0.0.0.0',
                                    int(address.split(':')[2])
                                    )
        task = loop.run_until_complete(server)

        try:
            print('Starting event loop...')
            loop.run_forever()
        except KeyboardInterrupt:
            pass
        finally:
            task.close()
            loop.close()


if __name__ == '__main__':

# Path: pyledger/server/handlers.py
# def handle_request(payload: bytes):
#     """
#     Handle a single request
# 
#     :param payload: Serialized PyledgerRequest message
#     :return:
#     """
#     handler = Handler()
#     message = PyledgerRequest()
#     response = PyledgerResponse()
# 
#     try:
#         message.ParseFromString(payload)
#     except DecodeError:
#         response.successful = False
#         response.data = b'Message not properly formatted'
#         return response.SerializeToString()
# 
#     if message.request not in handler_methods(handler):
#         response.successful = False
#         response.data = 'Request type {} not available'.format(message.request).encode()
#         return response.SerializeToString()
# 
#     else:
#         # Handle authentication
#         if message.request in permissions_registry:
#             user = User.from_name(message.user)
#             permission_required = permissions_registry[message.request]
# 
#             if not user.check_password(message.password):
#                 response.successful = False
#                 response.data = b'Wrong user and/or password'
#                 return response.SerializeToString()
# 
#             if user.get_permissions().value > permission_required.value:
#                 response.successful = False
#                 response.data = b'Not enough permissions'
#                 return response.SerializeToString()
# 
#             session = Session.from_key(message.session_key)
# 
#             if not session:
#                 response.successful = False
#                 response.data = b'Session not available'
#                 return response.SerializeToString()
# 
#             if not session.user == user:
#                 response.successful = False
#                 response.data = b'Session not owned by this user'
#                 return response.SerializeToString()
# 
#             if session.until < datetime.datetime.now():
#                 response.successful = False
#                 response.data = b'Session expired, restart your client'
#                 return response.SerializeToString()
# 
#         # Select the function from the handler
#         try:
#             print('Handling message', message)
#             successful, result = getattr(handler, message.request)(message)
#         except Exception as exc:
#             successful = False
#             result = b'Exception in user function: ' + repr(exc).encode('utf-8')
# 
#         response.successful = successful
#         response.data = result
#         return response.SerializeToString()
# 
# Path: pyledger/server/contract.py
# def register_contract(contract, description=''):
#     """
#     Register a contract and make it
#     :param contract:
#     :param description:
#     :return:
#     """
#     global contract_registry
# 
#     if contract.__class__.__name__ in contract_registry:
#         raise ValueError('A contract with the same name already registered')
#     else:
#         contract_registry[contract.__class__.__name__] = contract
# 
#     db_contract = Contract()
#     db_contract.name = contract.__class__.__name__
#     db_contract.created = datetime.datetime.now()
#     db_contract.description = description
# 
#     first_status = Status()
#     first_status.contract = db_contract
#     first_status.when = datetime.datetime.now()
#     first_status.attributes = status(contract).dump()
#     # Genesis key is the name of the contract
#     first_status.key = contract.__class__.__name__.encode('utf-8')
# 
#     DB.session.add(db_contract)
#     DB.session.add(first_status)
#     DB.session.commit()
# 
# class SimpleContract(BaseContract):
#     """
#     Contract that uses SimpleStatus for serialization.
# 
#     The goal of this class is to make a contact feel just like a Python class.
#     """
#     _status_class = SimpleStatus
# 
# Path: pyledger/server/db.py
# DB = Handler()
# 
# Path: pyledger/server/auth.py
# def create_master(password):
# def create_user(name, password):
# def allow(permission):
#     def decorator(func):
# def method_allow(permission):
#     def decorator(func):


# Path: pyledger/server/ws.py
from autobahn.asyncio.websocket import WebSocketServerProtocol, \
    WebSocketServerFactory
from pyledger.server.handlers import handle_request
from pyledger.server.contract import register_contract, SimpleContract
from pyledger.server.db import DB
from pyledger.server.auth import Permissions, method_allow
import asyncio

            print("unregistered client {}".format(client.peer))
            self.clients.remove(client)

    def broadcast(self, msg):
        print("broadcasting message '{}' ..".format(msg))
        for c in self.clients:
            c.sendMessage(msg, True)
            print("message sent to {}".format(c.peer))


def run_server(address="ws://127.0.0.1:9000"):
        factory = BroadcastServerFactory(address)
        factory.protocol = Protocol
        server = loop.create_server(factory,
                                    '0.0.0.0',
                                    int(address.split(':')[2])
                                    )
        task = loop.run_until_complete(server)

        try:
            print('Starting event loop...')
            loop.run_forever()
        except KeyboardInterrupt:
            pass
        finally:
            task.close()
            loop.close()


if __name__ == '__main__':

    DB.sync_tables()