#!/usr/bin/env python3
# Copyright 2016 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import socket
import sys
import os
import json

from openstackclient import shell as osc_shell
from io import StringIO

server_address = "/tmp/openstack.sock"

try:
    os.unlink(server_address)
except OSError:
    if os.path.exists(server_address):
        raise

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
print('starting up on %s' % server_address, file=sys.stderr)
sock.bind(server_address)

# Listen for incoming connections
sock.listen(1)

def send(sock, doc):
    jdoc = json.dumps(doc)
    sock.send(b'%d\n' % len(jdoc))
    sock.sendall(jdoc.encode('utf-8'))

def recv(sock):
    length_str = b''
    char = sock.recv(1)
    while char != b'\n':
        length_str += char
        char = sock.recv(1)

    total = int(length_str)

    # use a memoryview to receive the data chunk by chunk efficiently
    jdoc = memoryview(bytearray(total))
    next_offset = 0
    while total - next_offset > 0:
        recv_size = sock.recv_into(jdoc[next_offset:], total - next_offset)
        next_offset += recv_size
    try:
        doc = json.loads(jdoc.tobytes())
    except (TypeError, ValueError) as e:
        raise Exception('Data received was not in JSON format')
    return doc

while True:
    csock, client_address = sock.accept()
    try:
        doc = recv(csock)

        print("%s %s" % (doc["app"], doc["argv"]), file=sys.stderr)
        oldenv = {}
        for name in doc["env"].keys():
            oldenv[name] = os.environ.get(name, None)
            os.environ[name] = doc["env"][name]

        try:
            old_stdout = sys.stdout
            old_stderr = sys.stderr
            my_stdout = sys.stdout = StringIO()
            my_stderr = sys.stderr = StringIO()

            class Exit(BaseException):
                def __init__(self, status):
                    self.status = status

            def noexit(stat):
                raise Exit(stat)

            sys.exit = noexit

            if doc["app"] == "openstack":
                sh = osc_shell.OpenStackShell()
                ret = sh.run(doc["argv"])
            else:
                print("Unknown application %s" % doc["app"], file=sys.stderr)
                ret = 1
        except Exit as e:
            ret = e.status
        finally:
            sys.stdout = old_stdout
            sys.stderr = old_stderr

            for name in oldenv.keys():
                if oldenv[name] is None:
                    del os.environ[name]
                else:
                    os.environ[name] = oldenv[name]

        send(csock, {
            "stdout": my_stdout.getvalue(),
            "stderr": my_stderr.getvalue(),
            "status": ret,
        })

    except BaseException as e:
        print(e, file=sys.stderr)
    finally:
        csock.close()
