import "@fluencelabs/aqua-lib/builtin.aqua"

data EchoResult:
  echo: string

service EchoService:
  echo: []string -> []EchoResult

service GreetingService("service-id"):
    greeting: string, bool -> string

-- basic echo service: string array, return array of structs
func echo(names: []string, node: string, echo_service: string) -> []EchoResult:
  on node:
    EchoService echo_service
    res <- EchoService.echo(names)
  <- res


func greeting(name:string, greet:bool, node:string, greeting_service_id: string) -> string:
  on node:
    GreetingService greeting_service_id
    res <- GreetingService.greeting(name, greet)
  <- res

-- call echo service and and sequentailly call greeting service on each name
-- one service, on one node for all processing needs
func echo_greeting_seq(names: []string, greet: bool, node: string, echo_service_id: string,greeting_service_id: string) -> []string:
  res: *string
  on node:
    EchoService echo_service_id
    GreetingService greeting_service_id
    echo_names <- EchoService.echo(names)
    -- <- echo_names
    for result <- echo_names:
      res <- GreetingService.greeting(result.echo, greet)
  <- res


data NodeServicePair:
  node: string
  service_id: string

-- revised Aqua function to accommodate (node, service) separation 
func echo_greeting_seq_2(names: []string, greet: bool, echo_topo: NodeServicePair, greeting_topo: NodeServicePair) -> []string:
  res: *string
  on echo_topo.node:
    EchoService echo_topo.service_id
    echo_names <- EchoService.echo(names)
  
  on greeting_topo.node:
    GreetingService greeting_topo.service_id    
    for result <- echo_names:
      res <- GreetingService.greeting(result.echo, greet)
  <- res


data EchoServiceInput:
  node: string
  service_id: string
  names: []string

-- call parallel with echo service
func echo_greeting_par(greet: bool, echo_service: EchoServiceInput, greeting_services: []NodeServicePair) -> []string:
    res: *string
    on echo_service.node:
        EchoService echo_service.service_id
        echo_results <- EchoService.echo(echo_service.names)
    
    for result <- echo_results:
      par for greeting_service <- greeting_services:
        GreetingService greeting_service.service_id
        on greeting_service.node:
          res <- GreetingService.greeting(result.echo, greet)
        Op.noop()
    join res[5]
    <- res
  
-- call parallel with echo service, alternate version
func echo_greeting_par_alternative(greet: bool, echo_service: EchoServiceInput, greeting_services: []NodeServicePair) -> []string:
    res: *string
    on echo_service.node:
        EchoService echo_service.service_id
        echo_results <- EchoService.echo(echo_service.names)
    
    for result <- echo_results:
      for greeting_service <- greeting_services:
        GreetingService greeting_service.service_id
        par on greeting_service.node:
          res <- GreetingService.greeting(result.echo, greet)
        Op.noop()
    join res[5]
    <- res
  

-- updated input struct
data GreetingServiceInput:
  node: string
  service_id: string
  greet: bool

func echo_greeting_par_improved(echo_service: EchoServiceInput, greeting_services: []GreetingServiceInput) -> []string:
    res: *string
    on echo_service.node:
        EchoService echo_service.service_id
        echo_results <- EchoService.echo(echo_service.names)
    
    for result <- echo_results:
      par for greeting_service <- greeting_services:
        GreetingService greeting_service.service_id
        on greeting_service.node:
          res <- GreetingService.greeting(result.echo, greeting_service.greet)
        Op.noop()
    join res[5]
    <- res
