#
# Copyright (c) 2011-2015, 2017-2018, 2020, 2023-2024, 2026 LAAS/CNRS
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software for any purpose
# with or without   fee is hereby granted, provided   that the above  copyright
# notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS  SOFTWARE INCLUDING ALL  IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR  BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR  ANY DAMAGES WHATSOEVER RESULTING  FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION,   ARISING OUT OF OR IN    CONNECTION WITH THE USE   OR
# PERFORMANCE OF THIS SOFTWARE.
#
#

# ros component generation.

template usage {*}{
    "\n"
    "ROS-based component generation.\n"
    "\n"
    "This template generates a GenoM component that uses the ROS\n"
    "middleware.\n"
    "\n"
    "Supported options:\n"
    "  -C, --directory=dir\toutput files in dir\n"
    "  -p, --preserve\tdo not overwrite existing files\n"
    "  -h. --help\t\tprint usage summary (this text)"
}

# defaults
set odir ros
engine mode +overwrite +move-if-change

# parse options
template options {
    -C - --directory	{ set odir [template arg] }
    -p - --preserve	{ engine mode -overwrite }
    -h - --help		{ puts [template usage]; exit 0 }
}
if {![llength $argv]} { puts [template usage]; exit 2 }

engine chdir $odir

# parse common services specification and input
set input [template arg files]
dotgen parse file \
    [file join [dotgen template builtindir] common/genom.gen]	\
    {*}$input

# normalized list of input
set path [dotgen input path]
set input [lmap f $input {file normalize [file join $path $f]}]

# component compositing not (yet?) supported
set comp [template arg components]
if {[llength $comp] > 1} {
  template fatal "component compositing not supported"
}

# common header for all files (copyright info from .gen file)
set header {/* <"[--- Generated by [dotgen genom version]. Do not edit - ]"> */

<'if {![catch {dotgen input notice} notice]} {
  puts [lang c; comment $notice]
}'>
}

# generate source files
set server_files {
  exception.cc
  main.cc
  control-task.cc
  control-codels.cc
  activities.cc
  remote.cc
  port.cc
  json.cc
  internals.h
  activities.h
  locals.h
  remote.h
  port.h
}

foreach f $server_files {
  template parse args $comp string $header \
      file $f file src/[$comp name]_[file tail $f]
}
foreach t [$comp tasks] {
  template parse args [list $comp $t] string $header \
      file exec-task.cc file src/[$comp name]_[$t name]-exec-task.cc
}

# generate C mappings for the server
template parse \
    string $header \
    string [language mapping [concat [dotgen types] [$comp codels]]] \
    file src/[$comp name]_c_types.h

# generate ros .msg/.srv and .action for interface types
template require ../common/genrosmsg.tcl
set msg_types [genrossrv $comp true]
set msg_types [genrosmsg $comp $msg_types]

# public exception list + remote
set exl [dict create]
foreach t [$comp throws] {
  foreach e [$t types] {
    dict set exl [$e mangle] $e
  }
}
foreach r [$comp remotes] {
  foreach t [$r throws] {
    foreach e [$t types] {
      dict set exl [$e mangle] $e
    }
  }
}
set exl [dict values $exl]

# generate type manipulation for all private types
template parse args [list [$comp types private]] \
    file common/typeops-c.h file src/typeops-c.h
template parse args [list $exl] \
    file common/jsonops-c.h file src/jsonops-c.h

# generate serialization for all public types
template parse \
    file ../common/genom-serialize.h file src/genom-serialize.h
template parse args [list $comp [$comp types extern]] \
    string $header file ../common/serialize.h file src/[$comp name]_serialize.h
template parse args $comp \
    file ../common/portlib.h file src/[$comp name]_portlib.h
template parse args [list $comp [concat [$comp services] [$comp remotes]]] \
    file ../common/service.h file src/[$comp name]_service.h
template parse args [list $comp [concat [$comp services] [$comp remotes]]] \
    file ../common/action.h file src/[$comp name]_action.h

# generate profiling code
template parse string $header \
    file [file join [dotgen template builtindir] common/prof.h] \
    file src/prof.h
template parse string $header \
    file [file join [dotgen template builtindir] common/prof.c] \
    file src/prof.c

# setup build environment
template parse args [list $comp $msg_types $input] \
    file ros.Makefile.am file Makefile.am
template parse args [list $comp $msg_types] \
    file ros.configure.ac file configure.ac
template parse file ../common/autoconf/ax_pthread.m4 file autoconf/ax_pthread.m4
template parse file ../common/autoconf/ax_boost_base.m4 \
    file autoconf/ax_boost_base.m4
template parse file ../common/autoconf/ax_boost_thread.m4 \
    file autoconf/ax_boost_thread.m4
template parse file ../common/autoconf/ag_ros.m4 file autoconf/ag_ros.m4

template parse args [list $comp $msg_types] \
    file ../common/ros.package.xml file [$comp name]_ros/package.xml

set deps [list]
foreach d [concat [dotgen input deps] [template deps]] {
  lappend deps "\$(srcdir)/depend.am: $d"
  lappend deps "$d:" {}
}
engine mode +overwrite -move-if-change
template parse raw [join $deps "\n"]\n file depend.am
