/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * License); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


apply(plugin: "org.apache.beam.module")
apply(plugin: "base")
apply(from: "$project.rootDir/playground/backend/containers/git-functions.gradle")
applyDockerNature()

def playgroundJobServerProject = "${project.path.replace("-container", "")}"

description = project(playgroundJobServerProject).description + " :: Container"

configurations {
  dockerDependency
}

dependencies {
  dockerDependency(project(path: playgroundJobServerProject, configuration: "shadow"))
}

tasks.register("generate") {
  dependsOn("playground_components:generate")

  dependsOn("generateCode")

  group = "build"
  description = "Generates all generated files."
}

tasks.register("printPath") {
  doLast {
    exec {
      executable("printenv")
      args("PATH")
    }
  }
}

tasks.register("analyze") {
  dependsOn("playground_components:generateCode")
  dependsOn("generateCode")

  group = "verification"
  description = "Analyze dart code"

  doLast {
    exec {
      executable("dart")
      args("analyze", "lib", "test")
    }
  }
}

tasks.register("pubGet") {
  group = "build"
  description = "Get packages for the frontend project"
  doLast {
    exec {
      executable("flutter")
      args("pub", "get")
    }
  }
}

tasks.register("format") {
  group = "build"
  description = "Idiomatically format Dart source code"
  doLast {
    exec {
      executable("dart")
      args("format", "lib", "test")
    }
  }
}

tasks.register("run") {
  group = "application"
  description = "Run application on Google Chrome"

  doLast {
    exec {
      executable("flutter")
      args("run", "-d", "chrome")
    }
  }
}

tasks.register("test") {
  dependsOn("playground_components:generateCode")
  dependsOn("generateCode")

  group = "verification"
  description = "flutter test"

  doLast {
    exec {
      executable("flutter")
      args("test")
    }
  }
}

tasks.register("precommit") {
  dependsOn("playground_components:precommit")

  dependsOn("analyze")
  dependsOn("test")
}

tasks.register("generateCode") {
  dependsOn("playground_components:generateCode")

  dependsOn("cleanFlutter")
  dependsOn("pubGet")

  group = "build"
  description = "Generate code"

  doLast {
    exec {
      executable("flutter")
      args("pub", "run", "build_runner", "build", "--delete-conflicting-outputs")
    }
  }
}

tasks.register("cleanFlutter") {
  group = "build"
  description = "Remove build artifacts"

  doLast {
    exec {
      executable("flutter")
      args("clean")
    }
  }
}

tasks.register("cleanGenerated") {
  dependsOn("playground_components:cleanGenerated")

  group = "build"
  description = "Remove build artifacts"

  doLast {
    println("Deleting:")

    deleteFilesByRegExp(".*\\.g\\.dart\$")
    deleteFilesByRegExp(".*\\.gen\\.dart\$")
    deleteFilesByRegExp(".*\\.mocks\\.dart\$")
  }
}

ext.deleteFilesByRegExp = { re ->
  // Prints file names.
  exec {
    executable("find")
    args("assets", "lib", "test", "-regex", re)
  }

  // Actually deletes them.
  exec {
    executable("find")
    args("assets", "lib", "test", "-regex", re, "-delete")
  }
}

tasks.register("integrationTest") {
  dependsOn("integrationTest_embedded_run")
  dependsOn("integrationTest_initial_urls")
  dependsOn("integrationTest_standalone_cancel_running_example")
  dependsOn("integrationTest_standalone_change_example_sdk_run")
  dependsOn("integrationTest_standalone_change_pipeline_options_and_run")
  dependsOn("integrationTest_standalone_default_examples")
  dependsOn("integrationTest_standalone_editing")
  dependsOn("integrationTest_standalone_example_selector")
  dependsOn("integrationTest_standalone_miscellaneous_ui")
  dependsOn("integrationTest_standalone_run_shortcuts")
  dependsOn("integrationTest_standalone_share_code")
}

tasks.register("integrationTest_embedded_run") {
  doLast {
    runIntegrationTest("embedded_run", "/")
  }
}

tasks.register("integrationTest_initial_urls") {
  doLast {
    runIntegrationTest("initial_urls", "/")
  }
}

tasks.register("integrationTest_standalone_cancel_running_example") {
  doLast {
    runIntegrationTest("standalone_cancel_running_example", "/")
  }
}

tasks.register("integrationTest_standalone_change_example_sdk_run") {
  doLast {
    runIntegrationTest("standalone_change_example_sdk_run", "/")
  }
}

tasks.register("integrationTest_standalone_change_pipeline_options_and_run") {
  doLast {
    runIntegrationTest("standalone_change_pipeline_options_and_run", "/")
  }
}

tasks.register("integrationTest_standalone_default_examples") {
  doLast {
    runIntegrationTest("standalone_default_examples", "/")
  }
}

tasks.register("integrationTest_standalone_editing") {
  doLast {
    runIntegrationTest("standalone_editing", "/")
  }
}

tasks.register("integrationTest_standalone_example_selector") {
  doLast {
    runIntegrationTest("standalone_example_selector", "/")
  }
}

tasks.register("integrationTest_standalone_miscellaneous_ui") {
  doLast {
    runIntegrationTest("standalone_miscellaneous_ui", "/")
  }
}

tasks.register("integrationTest_standalone_run_shortcuts") {
  doLast {
    runIntegrationTest("standalone_run_shortcuts", "/")
  }
}

tasks.register("integrationTest_standalone_share_code") {
  doLast {
    runIntegrationTest("standalone_share_code", "/")
  }
}

void runIntegrationTest(String path, String url) {
  // Run with -PdeviceId=web-server for headless tests.
  // Run with -PexamplesRepository=apache/beam -PexamplesRef=master to verify that deployed examples match the given branch or commit.
  String deviceId = project.hasProperty("deviceId") ? project.deviceId : "chrome"
  String examplesRepository = project.hasProperty("examplesRepository") ? project.examplesRepository : null
  String examplesRef = project.hasProperty("examplesRef") ? project.examplesRef : null

  List<String> flutterArgs = [
    "drive",
    "--driver=test_driver/integration_test.dart",
    "--target=integration_test/${path}_test.dart",
    "--web-launch-url='$url'",
    "--device-id=$deviceId",
  ]

  if (examplesRepository != null) {
    flutterArgs.add("--dart-define=examples-repository=$examplesRepository")
  }
  if (examplesRef != null) {
    flutterArgs.add("--dart-define=examples-ref=$examplesRef")
  }

  exec {
    executable("flutter")
    args(flutterArgs)
  }
}


task copyDockerfileDependencies(type: Copy) {
   group = "build"
   description = "Copy files that required to build docker container"
   copy {
      from(".")
      into("build/")
      exclude("build")
      exclude("Dockerfile")
   }
   copy {
      from("../playground")
      into("build/playground")
   }
}

docker {
  group = "build"
  description = "Build container for frontend application"
  name = containerImageName(
    name: project.docker_image_default_repo_prefix + "playground-frontend",
    root: project.rootProject.hasProperty(["docker-repository-root"])
            ? project.rootProject["docker-repository-root"]
            : project.docker_image_default_repo_root
  )
  files("./build/")
  buildArgs([
    'BUILD_COMMIT_HASH': getGitCommitHash(),
    'BUILD_COMMIT_SECONDS_SINCE_EPOCH': getGitCommitTimestamp(),
  ])
  tags(containerImageTags())
}

// Ensure that we build the required resources and copy and file dependencies from related projects
dockerPrepare.dependsOn(copyDockerfileDependencies)
