#
# Copyright (c) 2019, 2025-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.
#
#                                            Anthony Mallet on Thu May  2 2019
#
package require genomix

namespace eval genomix::localhost {
  upvar index index
  variable token


  # --- local --------------------------------------------------------------
  #
  proc localhost { } {
    variable token
    variable index

    if {![info exists token]} {
      set token genomix[incr index]
      set alias [interp alias {} $token {} genomix::localhost::ctl $token]
    }
    return $token
  }
  namespace export localhost


  # --- ctl ----------------------------------------------------------------
  #
  proc ctl { token cmd args } {
    switch $cmd {
      read {
        if {[llength $args] != 2} {
          error "wrong # args: $token $cmd client port"
        }
        lassign $args c port
        set sub [join [lassign [split $port /] name] /]
        return [genomix::json::json2dict \
                    [::genomix::client::$c read $name $sub]]
      }

      send {
        if {[llength $args] != 3} {
          error "wrong # args: $token $cmd client service inputdict"
        }

        lassign $args c service inputdict
        if {[catch {dict get $inputdict input} input]} { set input "{}" }

        set r [genomix::client::$c send $service $input]
        if {[dict exists $inputdict oneway]} {
          set r ""
        }
        return $r
      }

      pub {
        if {[llength $args] < 4 || [llength $args] > 5} {
          error "wrong # args: $token $cmd client port op id argdict"
        }
        lassign $args c port op id args
        if {[catch {dict get $args data} data]} { set data [dict create] }

        return [genomix::client::$c pub $port $op $id $data]
      }

      portconnect - portdisconnect {
        if {[llength $args] != 2} {
          error "wrong # args: $token $cmd client port"
        }
        lassign $args c port
        set sub [join [lassign [split $port /] name] /]
        return [::genomix::client::$c $cmd $name $sub]
      }

      abort - clean {
        if {[llength $args] != 2} {
          error "wrong # args: $token $cmd client rid"
        }
        lassign $args c rid
        return [genomix::client::$c $cmd $rid]
      }

      result {
        if {[llength $args] != 1} {
          error "wrong # args: $token result id"
        }
        lassign [split {*}$args :] module sep r
        return [genomix::module::result $token $module $r]
      }

      close {
        if {[llength $args]} {
          error "too many args: $args"
        }
        close $token
        return
      }

      rpath {
        if {[llength $args] != 1} {
          error "wrong # args: $token rpath path"
        }
        return [genomix::rpath $args]
      }

      load {
        if {![llength $args]} {
          error [concat "wrong # args: $token load client" \
                     "?-h? ?client options? ?as alias?"]
        }
        set args [lassign $args client]
        return [genomix::module::load $token $client {*}$args]
      }

      unload {
        if {[llength $args] != 1} {
          error "wrong # args: $token $cmd client"
        }
        genomix::module::forget $token $args
        rename genomix::client::$args {}
        return "unloaded $args"
      }

      path {
        if {[llength $args] != 1} {
          error "wrong # args: $token $cmd client"
        }
        return [genomix::client::$args path]
      }

      options {
        if {[llength $args] != 1} {
          error "wrong # args: $token $cmd client"
        }
        return [genomix::json::json2dict [genomix::usage $args]]
      }

      info {
        if {[llength $args] != 1} {
          error "wrong # args: $token $cmd client"
        }
        if {[catch {
          genomix::json::json2dict [genomix::client::$args info]
        } info]} {
          error "invalid metadata for $args: $info"
        }
        return $info
      }

      dlopen {
        if {[llength $args] != 2} {
          error "wrong # args: $token $cmd client optlist"
        }
        return [genomix::load [lindex $args 0] [lindex $args 1] \
                    ::genomix::localhost::event]
      }
    }

    error [concat "unknown command $cmd: should be close,"	\
               " reconnect, rpath, load, unload, path,"	\
               " result, options, info, send"]
  }

  proc event { module activity status jsonerr output} {
    variable token

    set e [list]
    lappend e [subst {"id":"${module}::$activity"}]
    lappend e [subst {"status":"$status"}]
    if {$jsonerr != ""} {
      lappend e [subst {"errmsg":$jsonerr}]
    }
    if {$output != ""} {
      lappend e [subst {"output":$output}]
    }
    set json "{[join $e ,]}"

    genomix::module::reply $token $json
  }
}


namespace eval genomix {
  namespace import localhost::*
}
