#!/usr/bin/env python3

import os
import sys
from argparse import ArgumentParser

import yaml
from mako.template import Template

"""
This script generates the data structures for the
phosphor-fan-monitor application.

A future improvement is to get the fan inventory names
from a separate file, so just that file could be generated
from the MRW.
"""


tmpl = """\
<%!
def indent(str, depth):
    return ''.join(4*' '*depth+line for line in str.splitlines(True))
%>\
<%def name="getCondParams(cond)" buffered="True">
%if (cond['name'] == 'propertiesMatch'):
std::vector<PropertyState>{
    %for i in cond['properties']:
    PropertyState{
        {
            "${i['object']}",
            "${i['interface']}",
            "${i['property']['name']}"
        },
        static_cast<${i['property']['type']}>(${str(i['property']['value']).lower()})
    },
    %endfor
}
%endif
</%def>\
/* This is a generated file. */
#include "fan_defs.hpp"
#include "types.hpp"
#include "groups.hpp"
#include "conditions.hpp"

using namespace phosphor::fan::monitor;
using namespace phosphor::fan::trust;

const std::vector<FanDefinition> fanDefinitions
{
%for fan_data in data.get('fans', {}):
    FanDefinition{"${fan_data['inventory']}",
                  ${fan_data.get('method', {})},
                  ${fan_data.get('functional_delay', 0)},
                  ${fan_data.get('allowed_out_of_range_time', {})},
                  ${fan_data['deviation']},
                  ${fan_data['num_sensors_nonfunc_for_fan_nonfunc']},
                  0, // Monitor start delay - not used in YAML configs
                  0, // Count interval - not used in YAML configs
                  std::nullopt, // nonfuncRotorErrorDelay - also not used here
                  std::nullopt, // fanMissingErrorDelay - also not used here
                  std::vector<SensorDefinition>{
                  %for sensor in fan_data['sensors']:
                  <%
                      #has_target is a bool, and we need a true instead of True
                      has_target = str(sensor['has_target']).lower()
                      target_interface = sensor.get(
                          'target_interface',
                          'xyz.openbmc_project.Control.FanSpeed')
                      target_path = sensor.get(
                          'target_path',
                          '')
                      factor = sensor.get('factor', 1)
                      offset = sensor.get('offset', 0)
                      threshold = sensor.get('threshold', 1)
                      ignore_above_max = str(sensor.get(
                          'ignore_above_max', False)).lower()
                  %> \
                      SensorDefinition{"${sensor['name']}",
                                       ${has_target},
                                       "${target_interface}",
                                       "${target_path}",
                                       ${factor},
                                       ${offset},
                                       ${threshold},
                                       ${ignore_above_max}},
                  %endfor
                  },
                  %if ('condition' in fan_data) and \
                  (fan_data['condition'] is not None):
                  make_condition(condition::${fan_data['condition']['name']}(\
                      ${indent(getCondParams(cond=fan_data['condition']), 5)}\
                  ))
                  %else:
                  {},
                  false // set_func_on_present. Hardcoded to false.
                  %endif
    },
%endfor
};

##Function to generate the group creation lambda.
##If a group were to ever need a different constructor,
##it could be handled here.
<%def name="get_lambda_contents(group)">
            std::vector<GroupDefinition> group{
            %for member in group['group']:
            <%
                in_trust = str(member.get('in_trust', "true")).lower()
            %>
                GroupDefinition{"${member['name']}", ${in_trust}},
            %endfor
            };
            return std::make_unique<${group['class']}>(group);
</%def>
const std::vector<CreateGroupFunction> trustGroups
{
%for group in data.get('sensor_trust_groups', {}):
    {
        []()
        {\
${get_lambda_contents(group)}\
        }
    },
%endfor
};
"""


if __name__ == "__main__":
    parser = ArgumentParser(
        description="Phosphor fan monitor definition parser"
    )

    parser.add_argument(
        "-m",
        "--monitor_yaml",
        dest="monitor_yaml",
        default="example/monitor.yaml",
        help="fan monitor definitional yaml",
    )
    parser.add_argument(
        "-o",
        "--output_dir",
        dest="output_dir",
        default=".",
        help="output directory",
    )
    args = parser.parse_args()

    if not args.monitor_yaml:
        parser.print_usage()
        sys.exit(1)

    with open(args.monitor_yaml, "r") as monitor_input:
        monitor_data = yaml.safe_load(monitor_input) or {}

    # Do some minor input validation
    for fan in monitor_data.get("fans", {}):
        if (fan["deviation"] < 0) or (fan["deviation"] > 100):
            sys.exit("Invalid deviation value " + str(fan["deviation"]))

    output_file = os.path.join(args.output_dir, "fan_monitor_defs.cpp")
    with open(output_file, "w") as output:
        output.write(Template(tmpl).render(data=monitor_data))
