# Path: service/client.py
# class Client():
#     """
#     A wrapper for RESTful requests made to a server.
#     """
# 
#     def __init__(self, url, port):
#         self._url = url
#         self._port = port
# 
#     @property
#     def url(self):
#         return self._url
# 
#     @property
#     def port(self):
#         return self._port
# 
#     def get(self, resource, default=None):
#         full_url = self.url + ":" + str(self.port) + resource
#         try:
#             r = requests.get(url = full_url)
#             data = json_lib.dumps(ast.literal_eval(r.text))
#             return json_lib.loads(data)
#         except Exception as e:
#             return default
# 
#     def post(self, resource, json, default=None):
#         full_url = self.url + ":" + str(self.port) + resource
#         try:
#             r = requests.post(
#                 url = full_url,
#                 json = json)
#             data = json_lib.dumps(ast.literal_eval(r.text))
#             return json_lib.loads(data)
#         except Exception as e:
#             return default
# 
# Path: service/server.py
# class Server():
#     """
#     A server builder class.
# 
#     Each server is extendable via adding restful components.
#     The underlying server is Flask.
# 
#     e.g.
#       Server("test_server", "30020")
#         .add_component_get("/get_route", get_component)
#         .add_component_post("/post_route", post_component)
#         .run()
#     """
#     def __init__(self, name, port):
#         self.app = Flask(name)
#         self.name = name
#         self.port = port
#         self.components = []
# 
#     def add_component_post(self, route, component):
#         self.components.append(component)
# 
#         def binder():
#             def binded():
#                 return component.receive_post()
#             binded.__name__ = self.name + route.replace("/", "_")
# 
#             return binded
# 
#         self.app.route(route, methods=['POST'])(binder())
#         return self
# 
#     def add_component_get(self, route, component):
#         self.components.append(component)
# 
#         def binder():
#             def binded():
#                 return component.receive_get()
#             binded.__name__ = self.name + route.replace("/", "_")
# 
#             return binded
# 
#         self.app.route(route, methods=['GET'])(binder())
#         return self
# 
#     def run(self):
#         self.app.run(host='0.0.0.0', port=int(self.port))
# 
# Path: service/components.py
# class Component():
#     __metaclass__ = abc.ABCMeta
#     """
#     A component class that receives JSON requests and returns stringyfied jsons.
# 
#     To implement a new component, extend this class.
#     """
# 
#     @abc.abstractmethod
#     def process(self, json):
#         pass
# 
#     def receive_post(self):
#         if request.method == "POST":
#             req = request.get_json()
#             output = self.process(req)
#             return str(output)
# 
#     def receive_get(self):
#         if request.method == "GET":
#             output = self.process("")
#             return str(output)
# 
# Path: dissemination/master.py
# MASTER_DEFAULT_PORT = 5000
# 
# Path: dissemination/graph_sharing.py
# class GraphSharing():
#     def __init__(self, graph_client=LocalClient(config["graph"])):
#         self.graph_client = graph_client
# 
#     def snapshoot(self):
#         """
#         Takes a snapshoot of the graph to multicast.
#         """
#         graph = self.graph_client.get("/graph")
#         return graph
# 
#     def update(self, graph):
#         """
#         Relays the graph merge to the graph_service.
#         """
#         self.graph_client.post("/merge", graph)
# 
# Path: dissemination/util.py
# def get_host_ip():
#     """Bind the process to a socket."""
#     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#     s.connect(("8.8.8.8", 80))
# 
#     ip = s.getsockname()[0]
#     s.close()
# 
#     return ip


import logging
import sys
import os
import time
import threading
import random
from service.client import Client
from service.server import Server
from service.components import Component
from clint.textui import colored
from dissemination.master import MASTER_DEFAULT_PORT
from dissemination.graph_sharing import GraphSharing
from dissemination.util import get_host_ip
from __future__ import absolute_import

logger = logging.getLogger(__name__)

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))



class SlaveMembership(Component):
    def __init__(self, slave):
        self.slave = slave

    def process(self, membership_list):
        """
        REST component request processing. Register the master on the slave.
        """
        logging.info(colored.green("Received membership list."))
        self.slave.update_membership(membership_list)

class HealthCheck(Component):
    def process(self, _):
        """The health check component is responsible for anouncing
        each slave that the master is working."""
        return {
            "healty" : "true"
        }


# Path: service/client.py
# class Client():
#     """
#     A wrapper for RESTful requests made to a server.
#     """
# 
#     def __init__(self, url, port):
#         self._url = url
#         self._port = port
# 
#     @property
#     def url(self):
#         return self._url
# 
#     @property
#     def port(self):
#         return self._port
# 
#     def get(self, resource, default=None):
#         full_url = self.url + ":" + str(self.port) + resource
#         try:
#             r = requests.get(url = full_url)
#             data = json_lib.dumps(ast.literal_eval(r.text))
#             return json_lib.loads(data)
#         except Exception as e:
#             return default
# 
#     def post(self, resource, json, default=None):
#         full_url = self.url + ":" + str(self.port) + resource
#         try:
#             r = requests.post(
#                 url = full_url,
#                 json = json)
#             data = json_lib.dumps(ast.literal_eval(r.text))
#             return json_lib.loads(data)
#         except Exception as e:
#             return default
# 
# Path: service/server.py
# class Server():
#     """
#     A server builder class.
# 
#     Each server is extendable via adding restful components.
#     The underlying server is Flask.
# 
#     e.g.
#       Server("test_server", "30020")
#         .add_component_get("/get_route", get_component)
#         .add_component_post("/post_route", post_component)
#         .run()
#     """
#     def __init__(self, name, port):
#         self.app = Flask(name)
#         self.name = name
#         self.port = port
#         self.components = []
# 
#     def add_component_post(self, route, component):
#         self.components.append(component)
# 
#         def binder():
#             def binded():
#                 return component.receive_post()
#             binded.__name__ = self.name + route.replace("/", "_")
# 
#             return binded
# 
#         self.app.route(route, methods=['POST'])(binder())
#         return self
# 
#     def add_component_get(self, route, component):
#         self.components.append(component)
# 
#         def binder():
#             def binded():
#                 return component.receive_get()
#             binded.__name__ = self.name + route.replace("/", "_")
# 
#             return binded
# 
#         self.app.route(route, methods=['GET'])(binder())
#         return self
# 
#     def run(self):
#         self.app.run(host='0.0.0.0', port=int(self.port))
# 
# Path: service/components.py
# class Component():
#     __metaclass__ = abc.ABCMeta
#     """
#     A component class that receives JSON requests and returns stringyfied jsons.
# 
#     To implement a new component, extend this class.
#     """
# 
#     @abc.abstractmethod
#     def process(self, json):
#         pass
# 
#     def receive_post(self):
#         if request.method == "POST":
#             req = request.get_json()
#             output = self.process(req)
#             return str(output)
# 
#     def receive_get(self):
#         if request.method == "GET":
#             output = self.process("")
#             return str(output)
# 
# Path: dissemination/master.py
# MASTER_DEFAULT_PORT = 5000
# 
# Path: dissemination/graph_sharing.py
# class GraphSharing():
#     def __init__(self, graph_client=LocalClient(config["graph"])):
#         self.graph_client = graph_client
# 
#     def snapshoot(self):
#         """
#         Takes a snapshoot of the graph to multicast.
#         """
#         graph = self.graph_client.get("/graph")
#         return graph
# 
#     def update(self, graph):
#         """
#         Relays the graph merge to the graph_service.
#         """
#         self.graph_client.post("/merge", graph)
# 
# Path: dissemination/util.py
# def get_host_ip():
#     """Bind the process to a socket."""
#     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#     s.connect(("8.8.8.8", 80))
# 
#     ip = s.getsockname()[0]
#     s.close()
# 
#     return ip


# Path: dissemination/slave.py
import logging
import sys
import os
import time
import threading
import random
from service.client import Client
from service.server import Server
from service.components import Component
from clint.textui import colored
from dissemination.master import MASTER_DEFAULT_PORT
from dissemination.graph_sharing import GraphSharing
from dissemination.util import get_host_ip

from __future__ import absolute_import

logger = logging.getLogger(__name__)

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))



class SlaveMembership(Component):
    def __init__(self, slave):
        self.slave = slave

    def process(self, membership_list):
        """
        REST component request processing. Register the master on the slave.
        """
        logging.info(colored.green("Received membership list."))
        self.slave.update_membership(membership_list)

class HealthCheck(Component):
    def process(self, _):
        """The health check component is responsible for anouncing
        each slave that the master is working."""
        return {
            "healty" : "true"
        }


class MessageReceiver(Component):