#!/usr/bin/env python
"""Executable Python script for testing the action proxy.
/*
 * 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.
 */

  This script is useful for testing the action proxy (or its derivatives)
  by simulating invoker interactions. Use it in combination with
  docker run <image> which starts up the action proxy.
  Example:
     docker run -i -t -p 8080:8080 dockerskeleton # locally built images may be referenced without a tag
     ./invoke.py init <action source file>
     ./invoke.py run '{"some":"json object as a string"}'

  For additional help, try ./invoke.py -h
"""

import os
import re
import sys
import json
import base64
import requests
import codecs
import argparse
try:
    import argcomplete
except ImportError:
    argcomplete = False

def main():
    try:
        args = parseArgs()
        exitCode = {
            'init' : init,
            'run'   : run
        }[args.cmd](args)
    except Exception as e:
        print(e)
        exitCode = 1
    sys.exit(exitCode)

def dockerHost():
    dockerHost = 'localhost'
    if 'DOCKER_HOST' in os.environ:
        try:
            dockerHost = re.compile('tcp://(.*):[\d]+').findall(os.environ['DOCKER_HOST'])[0]
        except Exception:
            print('cannot determine docker host from %s' % os.environ['DOCKER_HOST'])
            sys.exit(-1)
    return dockerHost

def containerRoute(args, path):
    return 'http://%s:%s/%s' % (args.host, args.port, path)

def parseArgs():
    parser = argparse.ArgumentParser(description='initialize and run an OpenWhisk action container')
    parser.add_argument('-v', '--verbose', help='verbose output', action='store_true')
    parser.add_argument('--host', help='action container host', default=dockerHost())
    parser.add_argument('-p', '--port', help='action container port number', default=8080, type=int)

    subparsers = parser.add_subparsers(title='available commands', dest='cmd')

    initmenu = subparsers.add_parser('init', help='initialize container with src or zip/tgz file')
    initmenu.add_argument('-b', '--binary', help='treat artifact as binary', action='store_true')
    initmenu.add_argument('main', nargs='?', default='main', help='name of the "main" entry method for the action')
    initmenu.add_argument('artifact', help='a source file or zip/tgz archive')

    runmenu = subparsers.add_parser('run', help='send arguments to container to run action')
    runmenu.add_argument('payload', nargs='?', help='the arguments to send to the action, either a reference to a file or an inline JSON object', default=None)

    if argcomplete:
        argcomplete.autocomplete(parser)
    return parser.parse_args()

def init(args):
    main = args.main
    artifact = args.artifact

    if artifact and (args.binary or artifact.endswith('.zip') or artifact.endswith('tgz') or artifact.endswith('jar')):
        with open(artifact, 'rb') as fp:
            contents = fp.read()
        contents = base64.b64encode(contents)
        binary = True
    elif artifact is not '':
        with(codecs.open(artifact, 'r', 'utf-8')) as fp:
            contents = fp.read()
        binary = False
    else:
        contents = None
        binary = False

    r = requests.post(
        containerRoute(args, 'init'),
        json = {"value": {"code": contents,
                          "binary": binary,
                          "main": main}})
    print(r.text)

def run(args):
    value = processPayload(args.payload)
    if args.verbose:
        print('Sending value: %s...' % json.dumps(value)[0:40])
    r = requests.post(containerRoute(args, 'run'), json = {"value": value})
    print(r.text)

def processPayload(payload):
    if payload and os.path.exists(payload):
        with open(payload) as fp:
            return json.load(fp)
    try:
        d = json.loads(payload if payload else '{}')
        if isinstance(d, dict):
            return d
        else:
            raise
    except:
        print('payload must be a JSON object.')
        sys.exit(-1)

if __name__ == '__main__':
    main()
