------------------------------------------------------------------------
--  action_skill.lua - Create skill module automatically for actions
--
--  Created: Thu Aug 26 11:51:33 2010
--  Copyright  2010  Tim Niemueller [www.niemueller.de]
--
------------------------------------------------------------------------
--  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 Library General Public License for more details.
--
--  Read the full text in the LICENSE.GPL file in the doc directory.
require("fawkes.modinit")

--- Skill module auto-generator for ROS simple actions.
-- This module can automatically generate skill modules for simple ROS
-- actions which do not need special treatment.
-- @author Tim Niemueller
module(..., fawkes.modinit.module_init)

local skillenv = require("skiller.skillenv")
require("actionlib")
require("skiller.ros.action_jumpstate")
require("skiller.skillhsm")
local ActionJumpState = skiller.ros.action_jumpstate.ActionJumpState
local SkillHSM = skiller.skillhsm.SkillHSM

debug = false

function param_doc(fields, indent)
    local indent = indent or ""
    local rv = ""

    for _, f in ipairs(fields) do
        if f.is_builtin then
            rv = rv .. indent .. f.name .. " (" .. f.type .. ")\n"
        else
            rv = rv .. indent .. f.name ..
                     " as a table with the following entries:\n" ..
                     param_doc(f.spec.fields, indent .. "  ")
        end
    end

    return rv
end

function use(module_name, action_name, action_type)
    local M = {}
    local skill_name = module_name:match(".([%w%d_]+)$")
    local action_var = action_name:match("/?([%w%d_]+)$")
    local action_spec = actionlib.get_actionspec(action_type)
    local start_state = skill_name:upper()

    skillenv.module_init(M)
    M.name = skill_name
    M.fsm = SkillHSM:new{name = M.name, start = start_state, debug = debug}
    M.depends_actions = {
        {v = action_var, name = action_name, type = action_type, reduced = true}
    }
    M.documentation = "Autogenerated skill for the " .. action_name .. " (" ..
                          action_type ..
                          ") action.\nThe skill provides the following " ..
                          "parameters which you must\npass as named arguments to the skill " ..
                          "call.\n\n" .. param_doc(action_spec.goal_spec.fields)

    skillenv.skill_module(M)

    M.fsm:define_states{
        export_to = M,
        {start_state, ActionJumpState, action_client = M[action_var]}
    }

    _G[module_name] = M
    package.loaded[module_name] = M

    skillenv.use_skill(module_name)

    return M
end
