/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * license agreements; and to You under the Apache License, version 2.0:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * This file is part of the Apache Pekko project, which was derived from Akka.
 */

/*
 * Copyright (C) 2015-2022 Lightbend Inc. <https://www.lightbend.com>
 */

package org.apache.pekko.stream.javadsl

import org.apache.pekko.stream.scaladsl
import org.apache.pekko.stream.{ Shape, Graph }
import org.apache.pekko.japi.function
import org.apache.pekko.NotUsed

private[stream] abstract class GraphCreate {
  /**
   * Creates a new [[Graph]] of the given [[Shape]] by passing a [[GraphDSL.Builder]] to the given create function.
   */
  def create[S <: Shape](block: function.Function[GraphDSL.Builder[NotUsed], S]): Graph[S, NotUsed] =
    scaladsl.GraphDSL.create() { b => block.apply(b.asJava) }

  /**
   * Creates a new [[Graph]] by importing the given graph `g1` and its [[Shape]]
   * along with the [[GraphDSL.Builder]] to the given create function.
   */
  def create[S1 <: Shape, S <: Shape, M](g1: Graph[S1, M],
      block: function.Function2[GraphDSL.Builder[M], S1, S]): Graph[S, M] =
    scaladsl.GraphDSL.createGraph(g1) { b => s => block.apply(b.asJava, s) }

  /**
   * Creates a new [[Graph]] by importing the given graphs and passing their [[Shape]]s
   * along with the [[GraphDSL.Builder]] to the given create function.
   */
  def create[S1 <: Shape, S2 <: Shape, S <: Shape, M1, M2, M](g1: Graph[S1, M1], g2: Graph[S2, M2], combineMat: function.Function2[M1, M2, M],
      block: function.Function3[GraphDSL.Builder[M], S1, S2, S]): Graph[S, M] =
    scaladsl.GraphDSL.createGraph(g1, g2)(combineMat.apply) { b => (s1, s2) => block.apply(b.asJava, s1, s2) }

  [3..21#/**
   * Creates a new [[Graph]] by importing the given graphs and passing their [[Shape]]s
   * along with the [[GraphDSL.Builder]] to the given create function.
   */
  def create1[[#S1 <: Shape#], S <: Shape, [#M1#], M]([#g1: Graph[S1, M1]#], combineMat: function.Function1[[#M1#], M],
      block: function.Function2[GraphDSL.Builder[M], [#S1#], S]): Graph[S, M] =
    scaladsl.GraphDSL.createGraph([#g1#])(combineMat.apply) { b => ([#s1#]) => block.apply(b.asJava, [#s1#]) }#

  ]
}
