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

package akka.stream.javadsl

import akka.stream.scaladsl
import akka.stream.{ Shape, Graph }
import akka.japi.function
import akka.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.create(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.create(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.create([#g1#])(combineMat.apply) { b => ([#s1#]) => block.apply(b.asJava, [#s1#]) }#

  ]
}
