#!/usr/bin/env python3
# pylint: disable=invalid-name
#  -*- coding: utf-8 -*-
# *****************************************************************************
#
# 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 of the License, 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, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Module authors:
#   Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
#   Alexander Lenz <alexander.lenz@frm2.tum.de>
#
# *****************************************************************************

import sys
from os import path

# Add import path for inplace usage
sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), '..')))

from secop.lib import generalConfig
from secop.logging import logger
from secop.server import Server
from secop.core import Attached
from secop.lib.enum import EnumMember


def rep(value):
    if isinstance(value, EnumMember):
        return repr(value.name)
    return repr(value)


def guess(value):
    try:
        return '%.16g' % float(value)
    except (TypeError, ValueError):
        return rep(value)


def triplequote(description):
    if '\n' in description:
        return "'''%s'''" % '\n    '.join(description.split('\n'))
    else:
        return repr(description)


def get_value(modobj, pname, value):
    prop = modobj.propertyDict.get(pname)
    if isinstance(prop, Attached):
        return value
    clsname = type(modobj).__qualname__
    if pname in {'extra_modules', 'single_module', 'rel_paths', 'json_file'} and clsname.startswith('Sea'):
        return value.split()
    if pname == 'extra_params' and clsname.startswith('Sim'):
        return [v.strip() for v in value.split(',')]
    if pname == 'remote_class' and type(modobj).__bases__[0].__name__.startswith('Proxy'):
        return value
    return getattr(modobj, pname)


generalConfig.defaults = {k: True for k in (
    'lazy_number_validation', 'disable_value_range_check', 'legacy_hasiodev', 'tolerate_poll_property')}
generalConfig.init()
logger.init('off')


def main(cfgs):
    stats = {}
    for name in cfgs:
        try:
            content = []
            srv = Server(name, logger.log, cfgfiles=name, interface=5000, testonly=True)
            if srv.node_cfg.get('class') is not None:
                stats[name] = 'skip router'
                continue
            if 'FRAPPY' in srv.module_cfg:
                stats[name] = 'skip genconfig'
                continue
            for modname, params in srv.module_cfg.items():
                classname = params['class']
                if classname == 'secop_psi.sea.SeaClient':
                    params['uri'] = 'none'
                if 'iodev' in params:
                    params['io'] = params.pop('iodev')
                if '.iodev' in params:
                    params['io'] = params.pop('.iodev')
            node = dict(srv.node_cfg)
            if 'description' in node:
                content.append('Node(%r,\n     %s,' % (node.pop('id'), triplequote(node.pop('description'))))
                interface = srv.interface_cfg.get('uri')
                if interface:
                    content.append('     interface=%r,' % interface)
                for k, v in node.items():
                    content.append('     %s=%s,' % (k, guess(v)))
                content.append(')\n')
            errors = srv._processCfg()
            if errors:
                content = ['# %s' % e[:120] for e in errors] + content
                stats[name] = ', '.join(errors[:2])
            for modname, modcfg in srv.module_cfg.items():
                modobj = srv.dispatcher._modules.get(modname)
                classname = modcfg.pop('class')
                content.append('Mod(%r,\n    %r,' % (modname, classname))
                description = modcfg.pop('description', None)
                if description is not None:
                    content.append('    %s,' % triplequote(description))
                result = {}
                for key, value in modcfg.items():
                    pname, _, prop = key.partition('.')
                    if not pname:
                        pname, prop = prop, ''
                    elif pname == 'uri' and value == 'none':
                        continue
                    if prop:
                        pobj = modobj.parameters[pname] if modobj else None
                        if pobj:
                            try:
                                propvalue = rep(getattr(pobj, prop))
                            except AttributeError:
                                propvalue = rep(getattr(pobj.datatype, prop))
                        else:
                            propvalue = guess(value)
                    else:
                        prop = 'value'
                        if modobj:
                            propvalue = rep(get_value(modobj, pname, value))
                        else:
                            propvalue = guess(value)
                    result.setdefault(pname, {})[prop] = propvalue
                undef = object()
                for pname, cfg in result.items():
                    value = cfg.pop('value', undef)
                    if not cfg:
                        content.append('    %s=%s,' % (pname, value))
                    else:
                        args = ['%s=%s' % kv for kv in cfg.items()]
                        if value is not undef:
                            args.insert(0, value)
                        joined = ' '.join(args)
                        head = '    %s=Param(' % pname
                        if len(joined) < 8:
                            content.append('%s%s),' % (head, ', '.join(args)))
                        else:
                            content.append('%s\n        %s,\n    ),' % (head, ',\n        '.join(args)))
                content.append(')\n')
            with open('%s' % name.replace('.cfg', '_cfg.py'), 'w') as f:
                f.write('\n'.join(content))
            stats[name] = '*' if name in stats else ''
        except KeyboardInterrupt:
            break
        except BaseException as e:
            stats[name] = repr(e)
            if len(cfgs) == 1:
                raise

    if len(cfgs) > 1:
        with open('convert.log', 'w') as f:
            f.write('\n'.join('%s: %s' % kv for kv in stats.items())+'\n')


if __name__ == '__main__':
    main(sys.argv[1:])
