# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Mobius Forensic Toolkit
# Copyright (C) 2008,2009,2010 Eduardo Aguiar
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
import mobius

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Extension Compiler class
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class Compiler (object):

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief return argument list for python function
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_argument_list (self, obj):
    args = []
    for a in obj.args:
      value = a.id
      if a.defaultvalue:
        value += '=%s' % a.defaultvalue
      args.append (value)

    if obj.use_varargs:
      args.append ('*args')

    if obj.use_kwds:
      args.append ('**kwds')

    return ', '.join (args)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief compile extension
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def compile (self, path, pyfile):
    extension = mobius.mediator.call ('extension.open', path)
    self.generate_py (extension, pyfile)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief generate python module
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def generate_py (self, extension, pyfile):
    fp = open (pyfile, 'w') 
    fp.write (extension.code + '\n')

    for service in extension.services:
      self.generate_py_service (fp, service)

    for callback in extension.callbacks:
      self.generate_py_callback (fp, callback)

    self.generate_py_start_api (fp, extension)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief generate service code
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def generate_py_service (self, fp, service):
    funcname = 'svc_' + service.id.replace ('.', '_').replace ('-', '_')
    arglist = self.get_argument_list (service)

    fp.write ('\n')
    fp.write ('# ' + ('=-' * 38) + '=\n')
    fp.write ('# service <%s> implementation\n' % service.id)
    fp.write ('# ' + ('=-' * 38) + '=\n')
    fp.write ('def %s (%s):\n' % (funcname, arglist))

    if service.code.strip ():
      fp.write ('  ' + service.code.replace ('\n', '\n  ') + '\n')
    else:
      fp.write ('  pass\n')

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief generate callback code
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def generate_py_callback (self, fp, callback):
    funcname = 'cb_' + callback.id.replace ('.', '_').replace ('-', '_')
    arglist = self.get_argument_list (callback)

    fp.write ('\n')
    fp.write ('# ' + ('=-' * 38) + '=\n')
    fp.write ('# handle <%s> event\n' % callback.id)
    fp.write ('# ' + ('=-' * 38) + '=\n')
    fp.write ('def %s (%s):\n' % (funcname, arglist))

    if callback.code.strip ():
      fp.write ('  ' + callback.code.replace ('\n', '\n  ') + '\n')
    else:
      fp.write ('  pass\n')

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief generate start api
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def generate_py_start_api (self, fp, extension):
    fp.write ('\n')
    fp.write ('# ' + ('=-' * 38) + '=\n')
    fp.write ('# API initialization\n')
    fp.write ('# ' + ('=-' * 38) + '=\n')
    fp.write ('def pvt_start_api ():\n')

    has_code = False

    # services
    for service in extension.services:
      funcname = 'svc_' + service.id.replace ('.', '_').replace ('-', '_')

      if service.is_autostarted:
        fp.write ("  gdata.mediator.advertise ('%s', %s)\n" % (service.id, funcname))
        has_code = True

    # callbacks
    for callback in extension.callbacks:
      funcname = 'cb_' + callback.id.replace ('.', '_').replace ('-', '_')

      if callback.is_autostarted:
        fp.write ("  gdata.mediator.connect ('%s', %s" % (callback.id, funcname))
        if callback.is_chain_end:
          fp.write (', True')
        fp.write (')\n')

        has_code = True

    # no code. Generate 'pass'
    if not has_code:
      fp.write ('  pass\n')
