#
# 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
#

"""Library for generating asciidoc documentation from a L{schema.Schema}"""

from collections import namedtuple
import sys
from .schema import quotestr


class SchemaWriter(object):
    """Write the schema as an asciidoc document"""

    def __init__(self, output, schema, quiet=True):
        self.output, self.schema, self.quiet = output, schema, quiet
        self._heading = 0
        # Options affecting how output is written

    def warn(self, message):
        if not self.quiet: print >>sys.stderr, message

    def write(self, text): self.output.write(text)

    def writeln(self, text=""): self.output.write(text+"\n")

    def para(self, text): self.write(text+"\n\n")

    def heading(self, text=None, sub=0):
        self._heading += sub
        if text: self.para("\n=%s %s" % ("="*self._heading, text))

    class Section(namedtuple("Section", ["writer", "heading"])):
        def __enter__(self): self.writer.heading(self.heading, sub=+1)
        def __exit__(self, ex, value, trace): self.writer.heading(sub=-1)

    def section(self, heading): return self.Section(self, heading)

    def attribute_qualifiers(self, attr, show_create=True, show_update=True):
        default = attr.default
        if isinstance(default, basestring) and default.startswith('$'):
            default = None  # Don't show defaults that are references, confusing.
        return ' (%s)' % (', '.join(
            filter(None, [str(attr.atype),
                          default and "default=%s" % quotestr(default),
                          attr.required and "required",
                          attr.unique and "unique",
                          show_create and attr.create and "`CREATE`",
                          show_update and attr.update and "`UPDATE`"
                      ])))

    def attribute_type(self, attr, holder=None, show_create=True, show_update=True):
        self.writeln("'%s'%s::" % (
            attr.name, self.attribute_qualifiers(attr, show_create, show_update)))
        if attr.description:
            self.writeln("  %s" % attr.description)
        else:
            self.warn("Warning: No description for %s in %s" % (attr, attr.defined_in.short_name))
        self.writeln()

    def attribute_types(self, holder):
        for attr in holder.my_attributes:
            self.attribute_type(attr, holder)

    def operation_def(self, op, holder):

        def request_response(what):
            message = getattr(op, what)
            if message:
                if message.body:
                    self.para(".%s body%s\n\n%s" % (
                        what.capitalize(), self.attribute_qualifiers(message.body),
                        message.body.description))
                if message.properties:
                    self.para(".%s properties" % (what.capitalize()))
                    for prop in message.properties.itervalues():
                        self.attribute_type(prop)

        with self.section("Operation %s" % op.name):
            if op.description: self.para(op.description)
            request_response("request")
            request_response("response")

    def operation_defs(self, entity_type):
        for op in entity_type.operation_defs.itervalues():
            self.operation_def(op, entity_type)

    def entity_type(self, entity_type, operation_defs=True):
        with self.section(entity_type.short_name):
            if entity_type.description:
                self.para('%s' % entity_type.description)
            else:
                self.warn("Warning no description for %s" % entity_type)
            if entity_type.operations:
                self.para("Operations allowed: `%s`\n\n" % "`, `".join(entity_type.operations))

            self.attribute_types(entity_type)
            if entity_type.operation_defs:
                self.operation_defs(entity_type)

    def entity_types_extending(self, base_name):
        base = self.schema.entity_type(base_name)
        for entity_type in self.schema.filter(lambda t: t.extends(base)):
            self.entity_type(entity_type)

