#!/usr/bin/env ${PY_STRING}

#
# Licensed to the Apache Software Foundation (ASF) undeugr 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.
#

from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function

import sys, json, re
import  qpid_dispatch_site
import argparse
try:
    from collections.abc import Mapping, Sequence
except ImportError:
    from collections import Mapping, Sequence

from qpid_dispatch.management.client import Node, Url
from qpid_dispatch_internal.tools.command import (UsageError, _qdmanage_parser, check_args,
                                                  main, opts_ssl_domain, opts_url, opts_sasl)
from qpid_dispatch_internal.management.qdrouter import QdSchema
from qpid_dispatch_internal.compat import PY_TEXT_TYPE
from qpid_dispatch_internal.compat import PY_STRING_TYPE

INTEGER_TYPE = "integer"

def attr_split(attrstr, qd_schema, type):
    """Split an attribute string of the form name=value or name to indicate None"""
    nv = attrstr.split("=", 1)
    if len(nv) == 1:
        return [nv[0], None]
    else:
        if nv[1] == "true":
            nv[1] = True
        elif nv[1] == "false":
            nv[1] = False
        elif type and qd_schema.entity_type(type) and qd_schema.entity_type(type).attribute(nv[0]).type == INTEGER_TYPE:
            nv[1] = int(nv[1])

        return nv


class QdManage():
    def __init__(self):
        self.qd_schema = QdSchema()
        self.prefix = 'org.apache.qpid.dispatch.'
        self.operations = ['QUERY', 'CREATE', 'READ', 'UPDATE', 'DELETE',
                           'GET-TYPES', 'GET-OPERATIONS', 'GET-ATTRIBUTES', 'GET-ANNOTATIONS',
                           'GET-MGMT-NODES', 'GET-SCHEMA', 'GET-LOG']
        self.op = _qdmanage_parser(self.operations)

    def clean_opts(self):
        attr_type = self.opts.type
        if attr_type:
            self.opts.type = self.long_type(attr_type)

    def run(self, argv):
        # Make all args unicode to avoid encoding arg values as AMQP bytes.
        al = [x.decode() if not isinstance(x, PY_TEXT_TYPE) else x
              for x in argv[1:]]
        self.opts, self.args = self.op.parse_known_args(al)
        self.clean_opts()
        if self.opts.indent == -1:
            self.opts.indent = None
        if len(self.args) == 0:
            raise UsageError("No operation specified")
        self.node = Node.connect(opts_url(self.opts), self.opts.router, self.opts.timeout,
                                 opts_ssl_domain(self.opts),
                                 opts_sasl(self.opts),
                                 edge_router=self.opts.edge_router)

        operation = self.args.pop(0)
        method = operation.lower().replace('-','_')
        if operation.upper() in self.operations and hasattr(self, method):
            getattr(self, method)() # Built-in operation
        else:
            self.operation(operation) # Custom operation

    def main(self, argv):
        return main(self.run, argv, self.op)

    def print_json(self, data):
        """Print data as JSON"""
        print("%s" % json.dumps(data, indent=self.opts.indent))

    def print_result(self, result):
        """Print a string result as-is, else try json dump, else print as-is"""
        if not result: return
        if isinstance(result, (PY_STRING_TYPE, PY_TEXT_TYPE)):
            print("%s" % result)
        else:
            try:
                self.print_json(result)
            except ValueError:
                print("%s" % result)

    def long_type(self, type):
        if not type or "." in type:
            return type

        if type in ('link', 'node'):
            return self.prefix + "router." + type

        if type in ('linkRoute', 'address', 'autoLink'):
            return self.prefix + "router.config." + type

        return self.prefix + type

    def call_node(self, method, *argnames, **kwargs):
        """Call method on node, use opts named in argnames"""
        names = set(argnames)

        attributes = kwargs.get('attributes')
        if attributes and attributes.get('type'):
            attributes['type'] = self.long_type(attributes['type'])

        for k in self.opts.__dict__:
            if k in names and hasattr(self.opts, k):
                kwargs[k] = getattr(self.opts, k)

        return getattr(self.node, method)(**kwargs)

    def call_bulk(self, func):
        """Call function for attributes from stdin or --attributes option"""
        if self.opts.stdin:
            data = json.load(sys.stdin)
            if isinstance(data, Mapping):
                self.print_json(func(data).attributes)
            elif isinstance(data, Sequence):
                self.print_json([func(attrs).attributes for attrs in data])
            else: raise ValueError("stdin is not a JSON map or list")
        else:
            self.print_json(func(self.opts.attributes).attributes)

    def query(self):
        """query [ATTR...]          Print attributes of entities."""
        if self.args:
            self.opts.attribute_names = self.args
        result = self.call_node('query', 'type', 'attribute_names')
        self.print_json(result.get_dicts(clean=True))

    def create(self):
        """create [ATTR=VALUE...]   Create a new entity."""
        if self.args:
            self.opts.attributes = dict(attr_split(arg, self.qd_schema, self.opts.type) for arg in self.args)
        self.call_bulk(lambda attrs: self.call_node('create', 'type', 'name', attributes=attrs))

    def read(self):
        """read                     Print attributes of selected entity."""
        check_args(self.args, 0)
        self.print_json(self.call_node('read', 'type', 'name', 'identity').attributes)

    def update(self):
        """update [ATTR=VALUE...]   Update an entity."""
        if self.args:
            self.opts.attributes = dict(attr_split(arg, self.qd_schema, self.opts.type) for arg in self.args)
        self.call_bulk(
            lambda attrs: self.call_node('update', 'type', 'name', 'identity', attributes=attrs))

    def delete(self):
        """delete                   Delete an entity"""
        check_args(self.args, 0)
        self.call_node('delete', 'type', 'name', 'identity')

    def get_types(self):
        """get-types [TYPE]         List entity types with their base types."""
        if not self.opts.type:
            self.opts.type = check_args(self.args, 1)[0]
        self.print_json(self.call_node('get_types', 'type'))

    def get_annotations(self):
        """get-annotations [TYPE]   List entity types with the annotations they implement."""
        if not self.opts.type:
            self.opts.type = check_args(self.args, 1)[0]
        self.print_json(self.call_node('get_annotations', 'type'))

    def get_attributes(self):
        """get-attributes [TYPE]    List entity types with their attributes."""
        if not self.opts.type:
            self.opts.type = check_args(self.args, 1)[0]
        self.print_json(self.call_node('get_attributes', 'type'))

    def get_operations(self):
        """get-operations [TYPE]    List entity types with their operations."""
        if not self.opts.type:
            self.opts.type = check_args(self.args, 1)[0]
        self.print_json(self.call_node('get_operations', 'type'))

    def get_mgmt_nodes(self):
        """get-mgmt-nodes           List of other known management nodes"""
        check_args(self.args, 0)
        self.print_json(self.call_node('get_mgmt_nodes'))

    def json_arg(self, value):
        try:
            return json.loads(value)
        except ValueError as e:
            if not re.search(r'["{}\[\]]', value): # Doesn't look like attempted JSON.
                return value    # Just treat as plain string
            raise ValueError("Invalid JSON '%s': %s" % (value, e))

    def operation(self, operation):
        """operation [ATTR=VALUE...]   Call custom operation with ATTR=VALUE as request properties. Use --body and --properties if specified."""
        properties = dict(attr_split(arg, self.qd_schema, self.opts.type) for arg in self.args or [])
        if self.opts.properties:
            properties.update(self.json_arg(self.opts.properties))
        body = None
        if self.opts.body:
            body = self.json_arg(self.opts.body)
        request = self.call_node('request', 'type', 'name', 'identity', operation=operation, body=body, **properties)
        self.print_result(self.node.call(request).body)

if __name__ == "__main__":
    sys.exit(QdManage().main(sys.argv))
