#!/usr/bin/env python

'''
Phosphor Fan Presence (PFP) YAML parser and code generator.

Parse the provided PFP configuration file and generate C++ code.

The parser workflow is broken down as follows:
  1 - Import the YAML configuration file 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 os
import sys
import yaml
from argparse import ArgumentParser
import mako.lookup
from sdbusplus.renderer import Renderer
from sdbusplus.namedelement import NamedElement


class InvalidConfigError(BaseException):
    '''General purpose config file parsing error.'''

    def __init__(self, path, msg):
        '''Display configuration file with the syntax
        error and the error message.'''

        self.config = path
        self.msg = msg


class NotUniqueError(InvalidConfigError):
    '''Within a config file names must be unique.
    Display the duplicate item.'''

    def __init__(self, path, cls, *names):
        fmt = 'Duplicate {0}: "{1}"'
        super(NotUniqueError, self).__init__(
            path, fmt.format(cls, ' '.join(names)))


def get_index(objs, cls, name):
    '''Items are usually rendered as C++ arrays and as
    such are stored in python lists.  Given an item name
    its class, find the item index.'''

    for i, x in enumerate(objs.get(cls, [])):
        if x.name != name:
            continue

        return i
    raise InvalidConfigError('Could not find name: "{0}"'.format(name))


def exists(objs, cls, name):
    '''Check to see if an item already exists in a list given
    the item name.'''

    try:
        get_index(objs, cls, name)
    except:
        return False

    return True


def add_unique(obj, *a, **kw):
    '''Add an item to one or more lists unless already present.'''

    for container in a:
        if not exists(container, obj.cls, obj.name):
            container.setdefault(obj.cls, []).append(obj)


class Indent(object):
    '''Help templates be depth agnostic.'''

    def __init__(self, depth=0):
        self.depth = depth

    def __add__(self, depth):
        return Indent(self.depth + depth)

    def __call__(self, depth):
        '''Render an indent at the current depth plus depth.'''
        return 4*' '*(depth + self.depth)


class ConfigEntry(NamedElement):
    '''Base interface for rendered items.'''

    def __init__(self, *a, **kw):
        '''Pop the class keyword.'''

        self.cls = kw.pop('class')
        super(ConfigEntry, self).__init__(**kw)

    def factory(self, objs):
        ''' Optional factory interface for subclasses to add
        additional items to be rendered.'''

        pass

    def setup(self, objs):
        ''' Optional setup interface for subclasses, invoked
        after all factory methods have been run.'''

        pass


class Sensor(ConfigEntry):
    '''Convenience type for config file method:type handlers.'''

    def __init__(self, *a, **kw):
        kw['class'] = 'sensor'
        kw.pop('type')
        self.policy = kw.pop('policy')
        super(Sensor, self).__init__(**kw)

    def setup(self, objs):
        '''All sensors have an associated policy.  Get the policy index.'''

        self.policy = get_index(objs, 'policy', self.policy)


class Gpio(Sensor, Renderer):
    '''Handler for method:type:gpio.'''

    def __init__(self, *a, **kw):
        self.key = kw.pop('key')
        self.physpath = kw.pop('physpath')
        self.devpath = kw.pop('devpath')
        kw['name'] = 'gpio-{}'.format(self.key)
        super(Gpio, self).__init__(**kw)

    def construct(self, loader, indent):
        return self.render(
            loader,
            'gpio.mako.hpp',
            g=self,
            indent=indent)

    def setup(self, objs):
        super(Gpio, self).setup(objs)


class Tach(Sensor, Renderer):
    '''Handler for method:type:tach.'''

    def __init__(self, *a, **kw):
        self.sensors = kw.pop('sensors')
        kw['name'] = 'tach-{}'.format('-'.join(self.sensors))
        super(Tach, self).__init__(**kw)

    def construct(self, loader, indent):
        return self.render(
            loader,
            'tach.mako.hpp',
            t=self,
            indent=indent)

    def setup(self, objs):
        super(Tach, self).setup(objs)


class Rpolicy(ConfigEntry):
    '''Convenience type for config file rpolicy:type handlers.'''

    def __init__(self, *a, **kw):
        kw.pop('type', None)
        self.fan = kw.pop('fan')
        self.sensors = []
        kw['class'] = 'policy'
        super(Rpolicy, self).__init__(**kw)

    def setup(self, objs):
        '''All policies have an associated fan and methods.
        Resolve the indices.'''

        sensors = []
        for s in self.sensors:
            sensors.append(get_index(objs, 'sensor', s))

        self.sensors = sensors
        self.fan = get_index(objs, 'fan', self.fan)


class AnyOf(Rpolicy, Renderer):
    '''Default policy handler (policy:type:anyof).'''

    def __init__(self, *a, **kw):
        kw['name'] = 'anyof-{}'.format(kw['fan'])
        super(AnyOf, self).__init__(**kw)

    def setup(self, objs):
        super(AnyOf, self).setup(objs)

    def construct(self, loader, indent):
        return self.render(
            loader,
            'anyof.mako.hpp',
            f=self,
            indent=indent)


class Fallback(Rpolicy, Renderer):
    '''Fallback policy handler (policy:type:fallback).'''

    def __init__(self, *a, **kw):
        kw['name'] = 'fallback-{}'.format(kw['fan'])
        super(Fallback, self).__init__(**kw)

    def setup(self, objs):
        super(Fallback, self).setup(objs)

    def construct(self, loader, indent):
        return self.render(
            loader,
            'fallback.mako.hpp',
            f=self,
            indent=indent)


class Fan(ConfigEntry):
    '''Fan directive handler.  Fans entries consist of an inventory path,
    optional redundancy policy and associated sensors.'''

    def __init__(self, *a, **kw):
        self.path = kw.pop('path')
        self.methods = kw.pop('methods')
        self.rpolicy = kw.pop('rpolicy', None)
        super(Fan, self).__init__(**kw)

    def factory(self, objs):
        ''' Create rpolicy and sensor(s) objects.'''

        if self.rpolicy:
            self.rpolicy['fan'] = self.name
            factory = Everything.classmap(self.rpolicy['type'])
            rpolicy = factory(**self.rpolicy)
        else:
            rpolicy = AnyOf(fan=self.name)

        for m in self.methods:
            m['policy'] = rpolicy.name
            factory = Everything.classmap(m['type'])
            sensor = factory(**m)
            rpolicy.sensors.append(sensor.name)
            add_unique(sensor, objs)

        add_unique(rpolicy, objs)
        super(Fan, self).factory(objs)


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

    @staticmethod
    def classmap(cls):
        '''Map render item class entries to the appropriate
        handler methods.'''

        class_map = {
            'anyof': AnyOf,
            'fan': Fan,
            'fallback': Fallback,
            'gpio': Gpio,
            'tach': Tach,
        }

        if cls not in class_map:
            raise NotImplementedError('Unknown class: "{0}"'.format(cls))

        return class_map[cls]

    @staticmethod
    def load(args):
        '''Load the configuration file.  Parsing occurs in three phases.
        In the first phase a factory method associated with each
        configuration file directive is invoked.  These factory
        methods generate more factory methods.  In the second
        phase the factory methods created in the first phase
        are invoked.  In the last phase a callback is invoked on
        each object created in phase two.  Typically the callback
        resolves references to other configuration file directives.'''

        factory_objs = {}
        objs = {}
        with open(args.input, 'r') as fd:
            for x in yaml.safe_load(fd.read()) or {}:

                # The top level elements all represent fans.
                x['class'] = 'fan'
                # Create factory object for this config file directive.
                factory = Everything.classmap(x['class'])
                obj = factory(**x)

                # For a given class of directive, validate the file
                # doesn't have any duplicate names.
                if exists(factory_objs, obj.cls, obj.name):
                    raise NotUniqueError(args.input, 'fan', obj.name)

                factory_objs.setdefault('fan', []).append(obj)
                objs.setdefault('fan', []).append(obj)

            for cls, items in factory_objs.items():
                for obj in items:
                    # Add objects for template consumption.
                    obj.factory(objs)

            # Configuration file directives reference each other via
            # the name attribute; however, when rendered the reference
            # is just an array index.
            #
            # At this point all objects have been created but references
            # have not been resolved to array indices.  Instruct objects
            # to do that now.
            for cls, items in objs.items():
                for obj in items:
                    obj.setup(objs)

        return Everything(**objs)

    def __init__(self, *a, **kw):
        self.fans = kw.pop('fan', [])
        self.policies = kw.pop('policy', [])
        self.sensors = kw.pop('sensor', [])
        super(Everything, self).__init__(**kw)

    def generate_cpp(self, loader):
        '''Render the template with the provided data.'''
        sys.stdout.write(
            self.render(
                loader,
                args.template,
                fans=self.fans,
                sensors=self.sensors,
                policies=self.policies,
                indent=Indent()))

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

    parser = ArgumentParser(
        description='Phosphor Fan Presence (PFP) YAML '
        'scanner and code generator.')

    parser.add_argument(
        '-i', '--input', dest='input',
        default=os.path.join(script_dir, 'example', 'example.yaml'),
        help='Location of config file to process.')
    parser.add_argument(
        '-t', '--template', dest='template',
        default='generated.mako.hpp',
        help='The top level template to render.')
    parser.add_argument(
        '-p', '--template-path', dest='template_search',
        default=os.path.join(script_dir, 'templates'),
        help='The space delimited mako template search path.')
    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=args.template_search.split(),
            disable_unicode=True)
    else:
        lookup = mako.lookup.TemplateLookup(
            directories=args.template_search.split())
    try:
        function = getattr(
            Everything.load(args),
            valid_commands[args.command])
        function(lookup)
    except InvalidConfigError as e:
        sys.stderr.write('{0}: {1}\n\n'.format(e.config, e.msg))
        raise
