#! /usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

"""
``ctx`` proxy client implementation.
"""

import argparse
import json
import os
import sys
import urllib2


# Environment variable for the socket url (used by clients to locate the socket)
CTX_SOCKET_URL = 'CTX_SOCKET_URL'


class _RequestError(RuntimeError):

    def __init__(self, ex_message, ex_type, ex_traceback):
        super(_RequestError, self).__init__(self, '{0}: {1}'.format(ex_type, ex_message))
        self.ex_type = ex_type
        self.ex_message = ex_message
        self.ex_traceback = ex_traceback


def _http_request(socket_url, request, method, timeout):
    opener = urllib2.build_opener(urllib2.HTTPHandler)
    request = urllib2.Request(socket_url, data=json.dumps(request))
    request.get_method = lambda: method
    response = opener.open(request, timeout=timeout)

    if response.code != 200:
        raise RuntimeError('Request failed: {0}'.format(response))
    return json.loads(response.read())


def _client_request(socket_url, args, timeout, method='POST'):
    response = _http_request(
        socket_url=socket_url,
        request={'args': args},
        method=method,
        timeout=timeout
    )
    payload = response.get('payload')
    response_type = response.get('type')
    if response_type == 'error':
        ex_type = payload['type']
        ex_message = payload['message']
        ex_traceback = payload['traceback']
        raise _RequestError(ex_message, ex_type, ex_traceback)
    elif response_type == 'stop_operation':
        raise SystemExit(payload['message'])
    else:
        return payload


def _parse_args(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--timeout', type=int, default=30)
    parser.add_argument('--socket-url', default=os.environ.get(CTX_SOCKET_URL))
    parser.add_argument('--json-arg-prefix', default='@')
    parser.add_argument('-j', '--json-output', action='store_true')
    parser.add_argument('args', nargs='*')
    args = parser.parse_args(args=args)
    if not args.socket_url:
        raise RuntimeError('Missing CTX_SOCKET_URL environment variable '
                           'or socket_url command line argument. (ctx is supposed to be executed '
                           'within an operation context)')
    return args


def _process_args(json_prefix, args):
    processed_args = []
    for arg in args:
        if arg.startswith(json_prefix):
            arg = json.loads(arg[1:])
        processed_args.append(arg)
    return processed_args


def main(args=None):
    args = _parse_args(args)
    response = _client_request(
        args.socket_url,
        args=_process_args(args.json_arg_prefix, args.args),
        timeout=args.timeout)
    if args.json_output:
        response = json.dumps(response)
    else:
        if not response:
            response = ''
        response = str(response)
    sys.stdout.write(response)

if __name__ == '__main__':
    main()
