# Path: lib/PikaPublisher.py
# class PikaPublisher(Publisher):
#   """
#   Publisher implementation for RabbitMQ via the Pika client
#   """
# 
#   def __init__(self, device_name, device_id, rabbitmq_address, metric_name):
#     super(PikaPublisher, self).__init__(device_name, device_id, rabbitmq_address)
#     self.connection = None
#     self.channel = None
#     self.metric_name = metric_name
# 
# 
#   def publish(self, buffer_content):
#     key = "%s:%s:%s" % (self.device_id, self.device_name, self.metric_name)
#     self.channel.basic_publish(exchange=key,
#                                routing_key=key,
#                                body=json.dumps(buffer_content),
#                                properties=pika.BasicProperties(
#                                  delivery_mode=2,  # this makes the message persistent
#                                ))
# 
#   def connect(self):
#     credentials = pika.PlainCredentials('cloudbrain', 'cloudbrain')
# 
#     self.connection = pika.BlockingConnection(pika.ConnectionParameters(
#       host=self.host, credentials=credentials))
#     self.channel = self.connection.channel()
# 
#     key = "%s:%s:%s" % (self.device_id, self.device_name, self.metric_name)
#     self.channel.exchange_declare(exchange=key,
#                                   type='direct')
# 
#   def disconnect(self):
#     self.connection.close_file()
# 
# Path: lib/PipePublisher.py
# class PipePublisher(Publisher):
#   """
#   Publisher implementation for writing data to pipe
#   """
#   PIPE_WRITING_LOCKS = dict()
# 
#   def __init__(self, device_name, device_id, metric_name, pipe_name=None):
#     super(PipePublisher, self).__init__(device_name, device_id, None)
#     self.metric_name = metric_name
#     self.pipe_name = pipe_name
#     
# 
#   def get_lock(self):
#     lock = PipePublisher.PIPE_WRITING_LOCKS.get(self.pipe_name, None)
#     if lock is None:
#       lock = Lock()
#       PipePublisher.PIPE_WRITING_LOCKS[self.pipe_name] = lock
#     return lock
#     
#   def lock(self):
#     lock = self.get_lock()
#     lock.acquire(True)
# 
#   def unlock(self):
#     lock = self.get_lock()
#     lock.release()
#     
#   def publish(self, buffer_content):
#     key = "%s:%s:%s" % (self.device_id, self.device_name, self.metric_name)
#     out = {"key": key, 'body': buffer_content}
#     to_write = json.dumps(out)
# 
#     self.lock()
# 
#     self.pipe.write(to_write)
#     self.pipe.write("\n")
#     self.pipe.flush()
# 
#     self.unlock()
# 
#   def connect(self):
#     self.lock()
#     
#     if self.pipe_name is None:
#       self.pipe = sys.stdout
#     else:
#       if os.path.exists(self.pipe_name) and not stat.S_ISFIFO(os.stat(self.pipe_name).st_mode):
#         raise Exception("File '%s' exists and is not a named pipe." % self.pipe_name)
#       elif not os.path.exists(self.pipe_name):
#         os.mkfifo(self.pipe_name)
#       self.pipe = open(self.pipe_name, 'a')
# 
#     self.unlock()
#     
#   def disconnect(self):
#     if self.pipe_name is not None:
#       self.pipe.close()
#       os.remove(self.pipe_name)
# 
# Path: lib/devices.py
# def get_metrics_names(device_type):
#   """
#   Get metric names for a specific device type.
#   :return: list of metric names
#   """
#   metadata = [metadata for metadata in DEVICE_METADATA if metadata['device_name'] == device_type]
# 
#   if len(metadata) > 0:
#     metrics = metadata[0]['metrics']
#   else:
#     raise _DeviceNameNotFound("Could not find device name '%s' in metadata" % device_type)
# 
#   metric_names = []
#   for metric in metrics:
#     metric_names.append(metric['metric_name'])
# 
#   return metric_names
# 
# def get_supported_devices():
#   return [device['device_name'] for device in DEVICE_METADATA]
# 
# RABBITMQ_ADDRESS = 'localhost'
# 
# MOCK_DEVICE_ID = "mock"


import argparse
from lib.PikaPublisher import PikaPublisher
from lib.PipePublisher import PipePublisher
from lib.devices import get_metrics_names, get_supported_devices, RABBITMQ_ADDRESS, MOCK_DEVICE_ID
        from cloudbrain.connectors.MuseConnector import MuseConnector as Connector
        from lib.connectors.OpenBCIConnector import OpenBCIConnector as Connector

def main():
    opts = get_opts()
    mock_data_enabled = opts.mock
    device_name = opts.device_name
    device_id = opts.device_id
    cloudbrain_address = opts.cloudbrain
    buffer_size = int(opts.buffer_size)
    device_port = opts.device_port
    pipe_name = opts.output
    publisher = opts.publisher
    device_mac = opts.device_mac

    step_size = buffer_size
    if opts.step_size is not None:
        step_size = int(opts.step_size)

    run(device_name,
        mock_data_enabled,
        device_id,
        cloudbrain_address,
        buffer_size, step_size,
        device_port,
        pipe_name,
        publisher,
        device_mac)

def run(device_name="muse",
        mock_data_enabled=True,
        device_id=MOCK_DEVICE_ID,

# Path: lib/PikaPublisher.py
# class PikaPublisher(Publisher):
#   """
#   Publisher implementation for RabbitMQ via the Pika client
#   """
# 
#   def __init__(self, device_name, device_id, rabbitmq_address, metric_name):
#     super(PikaPublisher, self).__init__(device_name, device_id, rabbitmq_address)
#     self.connection = None
#     self.channel = None
#     self.metric_name = metric_name
# 
# 
#   def publish(self, buffer_content):
#     key = "%s:%s:%s" % (self.device_id, self.device_name, self.metric_name)
#     self.channel.basic_publish(exchange=key,
#                                routing_key=key,
#                                body=json.dumps(buffer_content),
#                                properties=pika.BasicProperties(
#                                  delivery_mode=2,  # this makes the message persistent
#                                ))
# 
#   def connect(self):
#     credentials = pika.PlainCredentials('cloudbrain', 'cloudbrain')
# 
#     self.connection = pika.BlockingConnection(pika.ConnectionParameters(
#       host=self.host, credentials=credentials))
#     self.channel = self.connection.channel()
# 
#     key = "%s:%s:%s" % (self.device_id, self.device_name, self.metric_name)
#     self.channel.exchange_declare(exchange=key,
#                                   type='direct')
# 
#   def disconnect(self):
#     self.connection.close_file()
# 
# Path: lib/PipePublisher.py
# class PipePublisher(Publisher):
#   """
#   Publisher implementation for writing data to pipe
#   """
#   PIPE_WRITING_LOCKS = dict()
# 
#   def __init__(self, device_name, device_id, metric_name, pipe_name=None):
#     super(PipePublisher, self).__init__(device_name, device_id, None)
#     self.metric_name = metric_name
#     self.pipe_name = pipe_name
#     
# 
#   def get_lock(self):
#     lock = PipePublisher.PIPE_WRITING_LOCKS.get(self.pipe_name, None)
#     if lock is None:
#       lock = Lock()
#       PipePublisher.PIPE_WRITING_LOCKS[self.pipe_name] = lock
#     return lock
#     
#   def lock(self):
#     lock = self.get_lock()
#     lock.acquire(True)
# 
#   def unlock(self):
#     lock = self.get_lock()
#     lock.release()
#     
#   def publish(self, buffer_content):
#     key = "%s:%s:%s" % (self.device_id, self.device_name, self.metric_name)
#     out = {"key": key, 'body': buffer_content}
#     to_write = json.dumps(out)
# 
#     self.lock()
# 
#     self.pipe.write(to_write)
#     self.pipe.write("\n")
#     self.pipe.flush()
# 
#     self.unlock()
# 
#   def connect(self):
#     self.lock()
#     
#     if self.pipe_name is None:
#       self.pipe = sys.stdout
#     else:
#       if os.path.exists(self.pipe_name) and not stat.S_ISFIFO(os.stat(self.pipe_name).st_mode):
#         raise Exception("File '%s' exists and is not a named pipe." % self.pipe_name)
#       elif not os.path.exists(self.pipe_name):
#         os.mkfifo(self.pipe_name)
#       self.pipe = open(self.pipe_name, 'a')
# 
#     self.unlock()
#     
#   def disconnect(self):
#     if self.pipe_name is not None:
#       self.pipe.close()
#       os.remove(self.pipe_name)
# 
# Path: lib/devices.py
# def get_metrics_names(device_type):
#   """
#   Get metric names for a specific device type.
#   :return: list of metric names
#   """
#   metadata = [metadata for metadata in DEVICE_METADATA if metadata['device_name'] == device_type]
# 
#   if len(metadata) > 0:
#     metrics = metadata[0]['metrics']
#   else:
#     raise _DeviceNameNotFound("Could not find device name '%s' in metadata" % device_type)
# 
#   metric_names = []
#   for metric in metrics:
#     metric_names.append(metric['metric_name'])
# 
#   return metric_names
# 
# def get_supported_devices():
#   return [device['device_name'] for device in DEVICE_METADATA]
# 
# RABBITMQ_ADDRESS = 'localhost'
# 
# MOCK_DEVICE_ID = "mock"


# Path: tools/connect.py
import argparse
from lib.PikaPublisher import PikaPublisher
from lib.PipePublisher import PipePublisher
from lib.devices import get_metrics_names, get_supported_devices, RABBITMQ_ADDRESS, MOCK_DEVICE_ID
        from cloudbrain.connectors.MuseConnector import MuseConnector as Connector
        from lib.connectors.OpenBCIConnector import OpenBCIConnector as Connector


def main():
    opts = get_opts()
    mock_data_enabled = opts.mock
    device_name = opts.device_name
    device_id = opts.device_id
    cloudbrain_address = opts.cloudbrain
    buffer_size = int(opts.buffer_size)
    device_port = opts.device_port
    pipe_name = opts.output
    publisher = opts.publisher
    device_mac = opts.device_mac

    step_size = buffer_size
    if opts.step_size is not None:
        step_size = int(opts.step_size)

    run(device_name,
        mock_data_enabled,
        device_id,
        cloudbrain_address,
        buffer_size, step_size,
        device_port,
        pipe_name,
        publisher,
        device_mac)

def run(device_name="muse",
        mock_data_enabled=True,
        device_id=MOCK_DEVICE_ID,

        cloudbrain_address=RABBITMQ_ADDRESS,