# coding=utf8
from __future__ import unicode_literals, absolute_import, print_function

from . import nodes


class Composer(nodes.Visitor):

    def __init__(self):
        super(Composer, self).__init__()
        self._depth = 0
        self._width = 4

    @property
    def indention(self):
        return ' ' * (self._depth * self._width)

    def visit_Symbol(self, node):
        assert isinstance(node, nodes.Symbol)
        return node.name

    def visit_TypeName(self, node):
        assert isinstance(node, nodes.TypeName)
        return node.name

    def visit_LineComment(self, node):
        assert isinstance(node, nodes.LineComment)
        text = node.text
        if text:
            assert text.startswith('--')
            return ' ' + text.strip()
        return ''

    def visit_BlockComment(self, node):
        assert isinstance(node, nodes.BlockComment)
        text = node.text
        if text:
            assert text.startswith('{-')
            assert text.endswith('-}')
            s = ''
            for line in text.strip().split('\n'):
                s += self.indention + line.strip() + '\n'
            return s
        return ''

    def visit_Pragma(self, node):
        assert isinstance(node, nodes.Pragma)
        text = node.text
        if text:
            assert node.text.startswith('{-#')
            assert node.text.endswith('#-}')
            s = ''
            for line in text.strip().split('\n'):
                s += self.indention + line.strip() + '\n'
            return s
        return ''

    def visit_NamedType(self, node, type_name):
        assert isinstance(node, nodes.NamedType)
        return type_name

    def visit_ArrayType(self, node, element_type):
        assert isinstance(node, nodes.ArrayType)
        return '[' + element_type + ']'

    def visit_GenericInstanceType(self, node, type_name, type_arguments):
        assert isinstance(node, nodes.GenericInstanceType)
        return type_name + '[' + ', '.join(type_arguments) + ']'

    def visit__pre_RecordType(self, node, **kwargs):
        self._depth += 1
        return kwargs

    def visit_RecordType(self, node, entries):
        assert isinstance(node, nodes.RecordType)
        if len(entries) == 0:
            return '{}'
        s = '{\n'
        for e in entries:
            s += e
        self._depth -= 1
        s += self.indention + '}'
        return s

    def visit_RecordTypeEntry(self, node, symbol, element_type, block_comment, line_comment):
        assert isinstance(node, nodes.RecordTypeEntry)
        s = ''
        s += block_comment
        s += self.indention + symbol + ': ' + element_type
        s += line_comment
        s += '\n'
        return s

    def visit_UnionType(self, node, choices):
        assert isinstance(node, nodes.UnionType)
        return ' | '.join(choices)

    def visit_TypeDef(self, node, type_name, type_, block_comment, line_comment):
        assert isinstance(node, nodes.TypeDef)
        s = ''
        s += block_comment
        s += 'data ' + type_name + ' = ' + type_
        s += line_comment
        s += '\n'
        return s

    def visit_Code(self, node, members):
        assert isinstance(node, nodes.Code)
        return '\n'.join(members)


def compose(tree):
    return tree.accept(Composer())
