# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# Contributor(s):
#   Chris Jones <jones.chris.g@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****

import os, sys

from ipdl.ast import Visitor
from ipdl.ast import IN, OUT, INOUT, ASYNC, SYNC, RPC

class CodePrinter:
    def __init__(self, outf=sys.stdout, indentCols=4):
        self.outf = outf
        self.col = 0
        self.indentCols = indentCols

    def write(self, str):
        self.outf.write(str)

    def printdent(self, str=''):
        self.write((' '* self.col) + str)

    def println(self, str=''):
        self.write(str +'\n')

    def printdentln(self, str):
        self.write((' '* self.col) + str +'\n')

    def indent(self):  self.col += self.indentCols
    def dedent(self):  self.col -= self.indentCols


##-----------------------------------------------------------------------------
class IPDLCodeGen(CodePrinter, Visitor):
    '''Spits back out equivalent IPDL to the code that generated this.
Also known as pretty-printing.'''

    def __init__(self, outf=sys.stdout, indentCols=4, printed=set()):
        CodePrinter.__init__(self, outf, indentCols)
        self.printed = printed

    def visitTranslationUnit(self, tu):
        self.printed.add(tu.filename)
        self.println('//\n// Automatically generated by ipdlc\n//')
        CodeGen.visitTranslationUnit(self, tu)

    def visitCxxInclude(self, inc):
        self.println('include "'+ inc.file +'";')

    def visitProtocolInclude(self, inc):
        self.println('include protocol "'+ inc.file +'";')
        if inc.tu.filename not in self.printed:
            self.println('/* Included file:')
            IPDLCodeGen(outf=self.outf, indentCols=self.indentCols,
                        printed=self.printed).visitTranslationUnit(inc.tu)
        
            self.println('*/')

    def visitProtocol(self, p):
        self.println()
        for namespace in p.namespaces:  namespace.accept(self)

        self.println('%s protocol %s\n{'% (p.sendSemantics[0], p.name))
        self.indent()

        for mgs in p.managesStmts:
            mgs.accept(self)
        if len(p.managesStmts):  self.println()

        for msgDecl in p.messageDecls:  msgDecl.accept(self)
        self.println()

        for transStmt in p.transitionStmts:  transStmt.accept(self)

        self.dedent()
        self.println('}')
        self.write('}\n'* len(p.namespaces))

    def visitManagerStmt(self, mgr):
        self.printdentln('manager '+ mgr.name +';')

    def visitManagesStmt(self, mgs):
        self.printdentln('manages '+ mgs.name +';')

    def visitMessageDecl(self, msg):
        self.printdent('%s %s %s('% (msg.sendSemantics[0], msg.direction[0], msg.name))
        for i, inp in enumerate(msg.inParams):
            inp.accept(self)
            if i != (len(msg.inParams) - 1):  self.write(', ')
        self.write(')')
        if 0 == len(msg.outParams):
            self.println(';')
            return

        self.println()
        self.indent()
        self.printdent('returns (')
        for i, outp in enumerate(msg.outParams):
            outp.accept(self)
            if i != (len(msg.outParams) - 1):  self.write(', ')
        self.println(');')
        self.dedent()
