def resolve_simple_macros_in_string(self, c_line, data, macromodulations, timeperiods,
                                        args=None):
        # pylint: disable=too-many-locals, too-many-branches, too-many-nested-blocks
        """Replace macro in the command line with the real value

        :param c_line: command line to modify
        :type c_line: str
        :param data: objects list, use to look for a specific macro
        :type data:
        :param macromodulations: the available macro modulations
        :type macromodulations: dict
        :param timeperiods: the available timeperiods
        :type timeperiods: dict
        :param args: args given to the command line, used to get "ARGN" macros.
        :type args:
        :return: command line with '$MACRO$' replaced with values
        :rtype: str
        """
        # Now we prepare the classes for looking at the class.macros
        data.append(self)  # For getting global MACROS
        if hasattr(self, 'my_conf'):
            data.append(self.my_conf)  # For USERN macros

        # we should do some loops for nested macros
        # like $USER1$ hiding like a ninja in a $ARG2$ Macro. And if
        # $USER1$ is pointing to $USER34$ etc etc, we should loop
        # until we reach the bottom. So the last loop is when we do
        # not still have macros :)
        still_got_macros = True
        nb_loop = 0
        while still_got_macros:
            nb_loop += 1
            # Ok, we want the macros in the command line
            macros = self._get_macros(c_line)

            # Put in the macros the type of macro for all macros
            self._get_type_of_macro(macros, data)

            # We can get out if we do not have macros this loop
            still_got_macros = False
            if macros:
                still_got_macros = True

            # Now we get values from elements
            for macro in macros:
                # If type ARGN, look at ARGN cutting
                if macros[macro]['type'] == 'ARGN' and args is not None:
                    macros[macro]['val'] = self._resolve_argn(macro, args)
                    macros[macro]['type'] = 'resolved'
                # If object type, get value from a property
                if macros[macro]['type'] == 'object':
                    obj = macros[macro]['object']
                    if obj not in data:
                        continue
                    prop = obj.macros[macro]
                    if not prop:
                        continue
                    macros[macro]['val'] = self._get_value_from_element(obj, prop)
                    # Now check if we do not have a 'output' macro. If so, we must
                    # delete all special characters that can be dangerous
                    if macro in self.output_macros:
                        logger.debug("-> macro from: %s, %s = %s", obj, macro, macros[macro])
                        macros[macro]['val'] = self._delete_unwanted_caracters(macros[macro]['val'])
                # If custom type, get value from an object custom variables
                if macros[macro]['type'] == 'CUSTOM':
                    cls_type = macros[macro]['class']
                    # Beware : only cut the first _HOST or _SERVICE or _CONTACT value,
                    # so the macro name can have it on it..
                    macro_name = re.split('_' + cls_type, macro, 1)[1].upper()
                    logger.debug(" ->: %s - %s", cls_type, macro_name)
                    # Ok, we've got the macro like MAC_ADDRESS for _HOSTMAC_ADDRESS
                    # Now we get the element in data that have the type HOST
                    # and we check if it got the custom value
                    for elt in data:
                        if not elt or elt.__class__.my_type.upper() != cls_type:
                            continue
                        logger.debug("   : for %s: %s", elt, elt.customs)
                        if not getattr(elt, 'customs'):
                            continue
                        if '_' + macro_name in elt.customs:
                            macros[macro]['val'] = elt.customs['_' + macro_name]
                        logger.debug("   : macro %s = %s", macro, macros[macro]['val'])

                        # Then look on the macromodulations, in reverse order, so
                        # the last defined will be the first applied
                        mms = getattr(elt, 'macromodulations', [])
                        for macromodulation_id in mms[::-1]:
                            macromodulation = macromodulations[macromodulation_id]
                            if not macromodulation.is_active(timeperiods):
                                continue
                            # Look if the modulation got the value,
                            # but also if it's currently active
                            if "_%s" % macro_name in macromodulation.customs:
                                macros[macro]['val'] = macromodulation.customs["_%s" % macro_name]
                # If on-demand type, get value from an dynamic provided data objects
                if macros[macro]['type'] == 'ONDEMAND':
                    macros[macro]['val'] = self._resolve_ondemand(macro, data)

            # We resolved all we can, now replace the macros in the command call
            for macro in macros:
                c_line = c_line.replace("$%s$" % macro, "%s" % (macros[macro]['val']))

            # A $$ means we want a $, it's not a macro!
            # We replace $$ by a big dirty thing to be sure to not misinterpret it
            c_line = c_line.replace("$$", "DOUBLEDOLLAR")

            if nb_loop > 32:  # too much loop, we exit
                still_got_macros = False

        # We now replace the big dirty token we made by only a simple $
        c_line = c_line.replace("DOUBLEDOLLAR", "$")

        return c_line.strip()
Replace macro in the command line with the real value

        :param c_line: command line to modify
        :type c_line: str
        :param data: objects list, use to look for a specific macro
        :type data:
        :param macromodulations: the available macro modulations
        :type macromodulations: dict
        :param timeperiods: the available timeperiods
        :type timeperiods: dict
        :param args: args given to the command line, used to get "ARGN" macros.
        :type args:
        :return: command line with '$MACRO$' replaced with values
        :rtype: str