#!/usr/bin/env python3
"""tojson.py

Created by Thomas Mangin on 2014-12-22.
Copyright (c) 2009-2017 Exa Networks. All rights reserved.
License: 3-clause BSD. (See the COPYRIGHT file)
"""


import os
import sys
import time
import signal
import thread
import subprocess
from collections import deque

from exabgp.reactor.api.transcoder import Transcoder
from exabgp.reactor.api.processes import preexec_helper


# test = """\
# { "exabgp": "3.5.0", "time": 1430238962.74, "host" : "mangin.local", "pid" : 37912, "ppid" : 37903, "type": "state", "neighbor": { "address": { "local": "82.219.212.34", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "state": "down", "reason": "out loop, peer reset, message [closing connection] error[the TCP connection was closed by the remote end]"} }
# { "exabgp": "3.5.0", "time": 1430238928.75, "host" : "mangin.local", "pid" : 37912, "ppid" : 37903, "type": "state", "neighbor": { "address": { "local": "82.219.212.34", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "state": "up"} }
# { "exabgp": "3.5.0", "time": 1430293452.31, "host" : "mangin.local", "pid" : 57788, "ppid" : 57779, "type": "open", "neighbor": { "address": { "local": "172.20.10.6", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "direction": "send", "message": { "category": 1, "header": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00AF01", "body": "04FFFE00B4800000009202060104000100010206010400010002020601040001000402060104000100800206010400010085020601040001008602060104000200010206010400020080020601040002008502060104000200860206010400190041020641040000FFFE0230402E84B00001018000010280000104800001808000018580000186800002018000028080000285800002868000194180" } } }
# { "exabgp": "3.5.0", "time": 1430293452.32, "host" : "mangin.local", "pid" : 57788, "ppid" : 57779, "type": "open", "neighbor": { "address": { "local": "172.20.10.6", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "direction": "receive", "message": { "category": 1, "header": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00AF01", "body": "04FFFD00B47F0000009202060104000100010206010400010002020601040001000402060104000100800206010400010085020601040001008602060104000200010206010400020080020601040002008502060104000200860206010400190041020641040000FFFD0230402E84B00001018000010280000104800001808000018580000186800002018000028080000285800002868000194180" } } }
# { "exabgp": "3.5.0", "time": 1430238928.75, "host" : "mangin.local", "pid" : 37912, "ppid" : 37903, "type": "update", "neighbor": { "address": { "local": "82.219.212.34", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "direction": "receive", "message": { "category": 2, "header": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF005002", "body": "0000002740010100400212020400000001000000020000000300000004400304010101018004040000006408630858084D08420837082C08210816080B" } } }
# { "exabgp": "3.5.0", "time": 1430238928.76, "host" : "mangin.local", "pid" : 37912, "ppid" : 37903, "type": "update", "neighbor": { "address": { "local": "82.219.212.34", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "direction": "receive", "message": { "category": 2, "header": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF001E02", "body": "00000007900F0003001941" } } }
# { "exabgp": "3.5.0", "time": 1430238928.76, "host" : "mangin.local", "pid" : 37912, "ppid" : 37903, "type": "update", "neighbor": { "address": { "local": "82.219.212.34", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "direction": "receive", "message": { "category": 2, "header": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF001E02", "body": "00000007900F0003000286" } } }
# { "exabgp": "3.5.0", "time": 1430238928.76, "host" : "mangin.local", "pid" : 37912, "ppid" : 37903, "type": "update", "neighbor": { "address": { "local": "82.219.212.34", "peer": "127.0.0.1" }, "asn": { "local": "65534", "peer": "65533" }, "direction": "receive", "message": { "category": 2, "header": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF001E02", "body": "00000007900F0003000285" } } }
# """.split('\n')


# XXX: We do not accept input from the forked application


class Application:
    Q = deque()
    running = True

    @staticmethod
    def _signal(_, __):
        Application.running = False

    def process(self):
        run = sys.argv[1:]
        if not run:
            sys.stderr.write('no consummer program provided\n')
            sys.exit(1)

        # Prevent some weird termcap data to be created at the start of the PIPE
        # \x1b[?1034h (no-eol) (esc)
        os.environ['TERM'] = 'dumb'

        try:
            sub = subprocess.Popen(
                run,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                preexec_fn=preexec_helper,
                # This flags exists for python 2.7.3 in the documentation but on on my MAC
                # creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
            )
        except (subprocess.CalledProcessError, OSError, ValueError):
            sys.stderr.write('could not start subprocess\n')
            sys.exit(1)

        return sub

    def __init__(self):
        thread.start_new_thread(self.reader, (os.getpid(),))
        signal.signal(signal.SIGTERM, Application._signal)
        self.sub = self.process()
        self.transcoder = Transcoder('json', 'json')
        self.main()

    # def test_reader (self,myself):
    # 	while len(test):
    # 		# line = sys.stdin.readline().strip()
    # 		line = test.pop(0)
    # 		if line:
    # 			self.Q.append(line)
    # 	time.sleep(2)
    # 	os.kill(myself,signal.SIGTERM)

    def reader(self, myself):
        ok = True
        line = ''
        while True:
            line = sys.stdin.readline().strip()
            if ok:
                if not line:
                    ok = False
                    continue
            elif not line:
                break
            else:
                ok = True
            self.Q.append(line)
        os.kill(myself, signal.SIGTERM)

    def main(self):
        while self.running or len(self.Q):
            try:
                line = self.Q.popleft()
                self.sub.stdin.write(self.transcoder.convert(line))
                self.sub.stdin.flush()
            except IndexError:
                # no data on the Q to read
                time.sleep(0.1)
            except OSError:
                # subprocess died
                sys.stderr.write('subprocess died\n')
                sys.exit(1)


if __name__ == '__main__':
    try:
        Application()
    except KeyboardInterrupt:
        pass
