#!/usr/bin/python
# -*- coding: UTF-8 -*-

import time
from datetime import datetime, timedelta
import zmq
import json
import numpy as np
from threading import Thread
import argparse
import pprint

REQUEST_TIMEOUT = 5000
RETRIES = 5
SERVER_ENDPOINT = 'tcp://localhost:4444'


def send(dato):
    '''
    Function to send data to server
    '''
    context = zmq.Context()
    socket = context.socket(zmq.REQ)
    socket.connect(SERVER_ENDPOINT)
    poll = zmq.Poller()
    poll.register(socket, zmq.POLLIN)
    retries = RETRIES
    while True:
        print(dato['plot'])
        socket.send_json(dato)
        socks = dict(poll.poll(REQUEST_TIMEOUT))
        if socks.get(socket) == zmq.POLLIN:
            reply = socket.recv_string()
            if reply == 'ok':
                print(('Server replied (%s)' % reply))
                break
            else:
                print(('Malformed reply from server: %s' % reply))
        else:
            print(('No response from server, retries left {}'.format(retries)))
        socket.setsockopt(zmq.LINGER, 0)
        socket.close()
        poll.unregister(socket)
        retries -= 1
        if retries == 0:
            print('Server seems to be offline...')
            socket = context.socket(zmq.REQ)
            socket.connect(SERVER_ENDPOINT)
            poll.register(socket, zmq.POLLIN)
            break
        # Create new connection
        socket = context.socket(zmq.REQ)
        socket.connect(SERVER_ENDPOINT)
        poll.register(socket, zmq.POLLIN)


def main(realtime, code, date=None, interval=30):
    '''
    Simulate data to be sended to server
    '''

    if realtime:
        dt = datetime.now()
    else:
        dt = date

    while True:
        print(('Sending {} - {}'.format(code, dt)))

        data = {
            'pcolor': ('Spectra', np.round(np.random.rand(4, 60, 100)*5 + 10, 2).tolist()),
            'pcolorbuffer': ('RTI', np.round(np.random.rand(4, 100)*5 + 10, 2).tolist()),
            'scatterbuffer': ('Power noise', np.round(np.random.rand(4, 1) + np.array([[10],[11],[12],[13]]), 2).tolist())
        }

        dato = {
            'time': time.mktime(dt.timetuple()),
            'metadata': {
                'yrange': np.arange(80, 120, 40/100.).tolist(),
                'xrange': np.arange(-30, 30).tolist(),
                'localtime': True,
                'interval': interval,
                'type': '',
                },
            'code': code,
        }

        dt = dt + timedelta(seconds=interval)
        for plot, d in data.items():
            dato['plot'] = d[0]
            dato['metadata']['type'] = plot
            dato['data'] = d[1]
            send(dato)
            # t = Thread(target=send, args=(dato, ))
            # t.start()
        if realtime:
            time.sleep(interval)
        else:
            time.sleep(5)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='''This is a Client for
                                                    realtime app''')
    parser.add_argument('--date', action='store', default=None,
                        help='format: 2018/02/13 12:23:00')
    parser.add_argument('-r', action='store_true', dest='realtime',
                        default=None)
    parser.add_argument('-c', action='store', dest='code', default='172')
    parser.add_argument('-i', action='store', dest='interval', type=int,
                        default=30)

    results = parser.parse_args()
    if not results.realtime:
        try:
            results.date = datetime.strptime(results.date, '%Y/%m/%d %H:%M:%S')
        except:
            raise NameError('''You must specify a date (--date)
                            for non-realtime experiment''')
    main(results.realtime, results.code, results.date, results.interval)
