#!python
# Copyright (c) 2017 Qumulo, 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.

'''
A simple CLI wrapper around REST API endpoints.

Think of it like CURL but with a tiny bit more knowledge of the Qumulo
word: in particular, the ability to store credentials so you can use logged-in
endpoints easily.

Advantages of this are:

  - As a developer, while prototyping a new feature, you can hit the API
    manually even before creating the REST wrappers and qq subcommand.

  - As a customer experimenting with the REST API directly, this is another way
    to explore, outside of IODocs.

  - The existence of qqurl means that you don't *necessarily* have to make
    a qq subcommand for every feature of an API; you can choose to focus on
    the interesting ones, knowing that qqurl exists to fill gaps.
'''


import argparse
import os
import sys
import StringIO

import qumulo.lib.auth
import qumulo.lib.request

import qumulo.commands.login

# TODO ideas:
# - tab completion for URLs
# - tab completion for methods

def main_options(parser):
    parser.add_argument("method_or_url", nargs="*", default=[])
    parser.add_argument("--chunked", action="store_true",
        default=qumulo.lib.request.DEFAULT_CHUNKED,
        help="Force chunked transfer encoding for requests")
    parser.add_argument("--chunk-size", type=int,
        default=qumulo.lib.request.DEFAULT_CHUNK_SIZE_BYTES,
        help=("Set chunk size in bytes for chunked "
              "transfer encoding (default: %d)" %
              qumulo.lib.request.DEFAULT_CHUNK_SIZE_BYTES))
    parser.add_argument("--credentials-store",
        default=qumulo.lib.auth.credential_store_filename(),
        help="Write credentials to a custom path")
    parser.add_argument("--debug", action="store_true", default=False)
    parser.add_argument("--host", default="localhost")
    parser.add_argument("--no-credentials", action="store_true",
        default=False, help=argparse.SUPPRESS)
    parser.add_argument("--port", type=int, default=8000)
    parser.add_argument("-v", "--verbose", action="count", default=0)
    parser.add_argument("--timeout", type=int, default=None,
        help="Time (in seconds) to wait for response")

    parser.add_argument("-u", "--username", default=None)
    parser.add_argument("-p", "--password", default=None)

def qqurl_main(args):
    method = None
    url = None
    if args.method_or_url:
        if len(args.method_or_url) != 2:
            sys.stderr.write(
                "Basic Usage: "
                "qqurl [<method> <url>] [-u <username> [-p <password>]]\n")
            exit(1)
        method = args.method_or_url[0]
        url = args.method_or_url[1]
    if not (method and url) and not (args.username):
        raise Exception("Supply method & url or else log in with --username")

    conninfo = qumulo.lib.request.Connection(
        args.host, args.port, chunked=args.chunked,
        chunk_size=args.chunk_size, timeout=args.timeout)

    credentials = qumulo.lib.auth.get_credentials(args.credentials_store)

    if args.username:
        username = args.username
        if args.password is None:
            password = qumulo.lib.opts.read_password(prompt='Password: ')
        else:
            password = args.password

        login_resp, _ = qumulo.rest.auth.login(
            conninfo, credentials,
            username, password)
        qumulo.lib.auth.set_credentials(login_resp, args.credentials_store)
        credentials = qumulo.lib.auth.get_credentials(args.credentials_store)

    if method:
        if method not in ['GET', 'POST', 'PUT', 'DELETE']:
            raise Exception("Unimplemented method {}".format(method))

        if method in ['POST', 'PUT']:
            body = sys.stdin.read()
            result = qumulo.lib.request.rest_request(
                conninfo, credentials,
                method, url,
                body_file=StringIO.StringIO(body))
        else:
            result = qumulo.lib.request.rest_request(
                conninfo, credentials,
                method, url)
        print result

def main():
     parzer = argparse.ArgumentParser(description="Qumulo Simple REST Wrapper",
         add_help=True, prog=os.path.basename(sys.argv[0]))
     main_options(parzer)
     argz = parzer.parse_args(sys.argv[1:])
     qqurl_main(argz)

if __name__ == '__main__':
    sys.exit(main())
