#!/usr/bin/env python

'''Phosphor Inventory Manager YAML parser and code generator.

The parser workflow is broken down as follows:
  1 - Import YAML files as native python type(s) instance(s).
  2 - Create an instance of the Everything class from the
        native python type instance(s) with the Everything.load
        method.
  3 - The Everything class constructor orchestrates conversion of the
        native python type(s) instances(s) to render helper types.
        Each render helper type constructor imports its attributes
        from the native python type(s) instances(s).
  4 - Present the converted YAML to the command processing method
        requested by the script user.
'''

import sys
import os
import argparse
import subprocess
import yaml
import mako.lookup
import sdbusplus.property
from sdbusplus.namedelement import NamedElement
from sdbusplus.renderer import Renderer


class Interface(list):
    '''Provide various interface transformations.'''

    def __init__(self, iface):
        super(Interface, self).__init__(iface.split('.'))

    def namespace(self):
        '''Represent as an sdbusplus namespace.'''
        return '::'.join(['sdbusplus'] + self[:-1] + ['server', self[-1]])

    def header(self):
        '''Represent as an sdbusplus server binding header.'''
        return os.sep.join(self + ['server.hpp'])

    def __str__(self):
        return '.'.join(self)


class Argument(sdbusplus.property.Property):
    '''Bridge sdbusplus property typenames to syntatically correct c++.'''

    def __init__(self, **kw):
        self.value = kw.pop('value')
        self.cast = kw.pop('cast', None)
        super(Argument, self).__init__(**kw)

    def cppArg(self):
        '''Transform string types to c++ string constants.'''

        a = self.value
        if self.typeName == 'string':
            a = '"%s"' % a

        if self.cast:
            a = 'static_cast<%s>(%s)' % (self.cast, a)

        return a


class MethodCall(NamedElement, Renderer):
    '''Render syntatically correct c++ method calls.'''

    def __init__(self, **kw):
        self.namespace = kw.pop('namespace', [])
        self.template = kw.pop('template', '')
        self.pointer = kw.pop('pointer', False)
        self.args = \
            [Argument(**x) for x in kw.pop('args', [])]
        super(MethodCall, self).__init__(**kw)

    def bare_method(self):
        '''Provide the method name and encompassing
        namespace without any arguments.'''

        m = '::'.join(self.namespace + [self.name])
        if self.template:
            m += '<%s>' % self.template

        return m

    def call(self, loader, indent):
        return self.render(
            loader,
            'method.mako.cpp',
            method=self,
            indent=indent)

    def argument(self, loader, indent):
        return self.call(loader, indent)


class Filter(MethodCall):
    '''Provide common attributes for any filter.'''

    def __init__(self, **kw):
        kw['namespace'] = ['filters']
        super(Filter, self).__init__(**kw)


class Action(MethodCall):
    '''Provide common attributes for any action.'''

    def __init__(self, **kw):
        kw['namespace'] = ['actions']
        super(Action, self).__init__(**kw)


class DbusSignature(NamedElement, Renderer):
    '''Represent a dbus signal match signature.'''

    def __init__(self, **kw):
        self.sig = {x: y for x, y in kw.iteritems()}
        kw.clear()
        super(DbusSignature, self).__init__(**kw)

    def argument(self, loader, indent):
        return self.render(
            loader,
            'signature.mako.cpp',
            signature=self,
            indent=indent)


class DestroyObject(Action):
    '''Render a destroyObject action.'''

    def __init__(self, **kw):
        mapped = kw.pop('args')
        kw['args'] = [
            {'value': mapped['path'], 'type':'string'},
        ]
        super(DestroyObject, self).__init__(**kw)


class SetProperty(Action):
    '''Render a setProperty action.'''

    def __init__(self, **kw):
        mapped = kw.pop('args')
        member = Interface(mapped['interface']).namespace()
        member = '&%s' % '::'.join(
            member.split('::') + [NamedElement(
                name=mapped['property']).camelCase])

        memberType = Argument(**mapped['value']).cppTypeName

        kw['template'] = Interface(mapped['interface']).namespace()
        kw['args'] = [
            {'value': mapped['path'], 'type':'string'},
            {'value': mapped['interface'], 'type':'string'},
            {'value': member, 'cast': '{0} ({1}::*)({0})'.format(
                memberType,
                Interface(mapped['interface']).namespace())},
            mapped['value'],
        ]
        super(SetProperty, self).__init__(**kw)


class NoopAction(Action):
    '''Render a noop action.'''

    def __init__(self, **kw):
        kw['pointer'] = True
        super(NoopAction, self).__init__(**kw)


class NoopFilter(Filter):
    '''Render a noop filter.'''

    def __init__(self, **kw):
        kw['pointer'] = True
        super(NoopFilter, self).__init__(**kw)


class PropertyChanged(Filter):
    '''Render a propertyChanged filter.'''

    def __init__(self, **kw):
        mapped = kw.pop('args')
        kw['args'] = [
            {'value': mapped['interface'], 'type':'string'},
            {'value': mapped['property'], 'type':'string'},
            mapped['value']
        ]
        super(PropertyChanged, self).__init__(**kw)


class Event(NamedElement, Renderer):
    '''Render an inventory manager event.'''

    action_map = {
        'noop': NoopAction,
        'destroyObject': DestroyObject,
        'setProperty': SetProperty,
    }

    def __init__(self, **kw):
        self.cls = kw.pop('type')
        self.actions = \
            [self.action_map[x['name']](**x)
                for x in kw.pop('actions', [{'name': 'noop'}])]
        super(Event, self).__init__(**kw)


class MatchEvent(Event):
    '''Associate one or more dbus signal match signatures with
    a filter.'''

    filter_map = {
        'none': NoopFilter,
        'propertyChangedTo': PropertyChanged,
    }

    def __init__(self, **kw):
        self.signatures = \
            [DbusSignature(**x) for x in kw.pop('signatures', [])]
        self.filters = \
            [self.filter_map[x['name']](**x)
                for x in kw.pop('filters', [{'name': 'none'}])]
        super(MatchEvent, self).__init__(**kw)


class Everything(Renderer):
    '''Parse/render entry point.'''

    class_map = {
        'match': MatchEvent,
    }

    @staticmethod
    def load(args):
        # Invoke sdbus++ to generate any extra interface bindings for
        # extra interfaces that aren't defined externally.
        yaml_files = []
        extra_ifaces_dir = os.path.join(args.inputdir, 'extra_interfaces.d')
        if os.path.exists(extra_ifaces_dir):
            for directory, _, files in os.walk(extra_ifaces_dir):
                if not files:
                    continue

                yaml_files += map(
                    lambda f: os.path.relpath(
                        os.path.join(directory, f),
                        extra_ifaces_dir),
                    filter(lambda f: f.endswith('.interface.yaml'), files))

        genfiles = {
            'server-cpp': lambda x: '%s.cpp' % (
                x.replace(os.sep, '.')),
            'server-header': lambda x: os.path.join(
                os.path.join(
                    *x.split('.')), 'server.hpp')
        }

        for i in yaml_files:
            iface = i.replace('.interface.yaml', '').replace(os.sep, '.')
            for process, f in genfiles.iteritems():

                dest = os.path.join(args.outputdir, f(iface))
                parent = os.path.dirname(dest)
                if parent and not os.path.exists(parent):
                    os.makedirs(parent)

                with open(dest, 'w') as fd:
                    subprocess.call([
                        'sdbus++',
                        '-r',
                        extra_ifaces_dir,
                        'interface',
                        process,
                        iface],
                        stdout=fd)

        # Aggregate all the event YAML in the events.d directory
        # into a single list of events.

        events_dir = os.path.join(args.inputdir, 'events.d')
        yaml_files = filter(
            lambda x: x.endswith('.yaml'),
            os.listdir(events_dir))

        events = []
        for x in yaml_files:
            with open(os.path.join(events_dir, x), 'r') as fd:
                for e in yaml.safe_load(fd.read()).get('events', {}):
                    events.append(e)

        return Everything(
            *events,
            interfaces=Everything.get_interfaces(args))

    @staticmethod
    def get_interfaces(args):
        '''Aggregate all the interface YAML in the interfaces.d
        directory into a single list of interfaces.'''

        interfaces_dir = os.path.join(args.inputdir, 'interfaces.d')
        yaml_files = filter(
            lambda x: x.endswith('.yaml'),
            os.listdir(interfaces_dir))

        interfaces = []
        for x in yaml_files:
            with open(os.path.join(interfaces_dir, x), 'r') as fd:
                for i in yaml.safe_load(fd.read()):
                    interfaces.append(i)

        return interfaces

    def __init__(self, *a, **kw):
        self.interfaces = \
            [Interface(x) for x in kw.pop('interfaces', [])]
        self.events = [
            self.class_map[x['type']](**x) for x in a]
        super(Everything, self).__init__(**kw)

    def list_interfaces(self, *a):
        print ' '.join([str(i) for i in self.interfaces])

    def generate_cpp(self, loader):
        '''Render the template with the provided events and interfaces.'''
        with open(os.path.join(
                args.outputdir,
                'generated.cpp'), 'w') as fd:
            fd.write(
                self.render(
                    loader,
                    'generated.mako.cpp',
                    events=self.events,
                    interfaces=self.interfaces))


if __name__ == '__main__':
    script_dir = os.path.dirname(os.path.realpath(__file__))
    valid_commands = {
        'generate-cpp': 'generate_cpp',
        'list-interfaces': 'list_interfaces'
    }

    parser = argparse.ArgumentParser(
        description='Phosphor Inventory Manager (PIM) YAML '
        'scanner and code generator.')
    parser.add_argument(
        '-o', '--output-dir', dest='outputdir',
        default='.', help='Output directory.')
    parser.add_argument(
        '-d', '--dir', dest='inputdir',
        default=os.path.join(script_dir, 'example'),
        help='Location of files to process.')
    parser.add_argument(
        'command', metavar='COMMAND', type=str,
        choices=valid_commands.keys(),
        help='%s.' % " | ".join(valid_commands.keys()))

    args = parser.parse_args()

    if sys.version_info < (3, 0):
        lookup = mako.lookup.TemplateLookup(
            directories=[script_dir],
            disable_unicode=True)
    else:
        lookup = mako.lookup.TemplateLookup(
            directories=[script_dir])

    function = getattr(
        Everything.load(args),
        valid_commands[args.command])
    function(lookup)


# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
