#
# 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.
#

"""Tests for the Java external transforms."""

import argparse
import logging
import subprocess
import sys
from typing import Optional

import grpc
from mock import patch

import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions
from apache_beam.testing.test_pipeline import TestPipeline
from apache_beam.testing.util import assert_that
from apache_beam.testing.util import equal_to
from apache_beam.transforms.external import ImplicitSchemaPayloadBuilder
from apache_beam.utils import subprocess_server

# Protect against environments where apitools library is not available.
# pylint: disable=wrong-import-order, wrong-import-position
try:
  from apache_beam.runners.dataflow.internal import apiclient as _apiclient
except ImportError:
  apiclient = None
else:
  apiclient = _apiclient
# pylint: enable=wrong-import-order, wrong-import-position


class JavaExternalTransformTest(object):

  # This will be overwritten if set via a flag.
  expansion_service_jar: Optional[str] = None
  expansion_service_port: Optional[int] = None

  class _RunWithExpansion(object):
    def __init__(self):
      self._server = None

    def __enter__(self):
      if not (JavaExternalTransformTest.expansion_service_jar or
              JavaExternalTransformTest.expansion_service_port):
        raise RuntimeError('No expansion service jar or port provided.')

      JavaExternalTransformTest.expansion_service_port = (
          JavaExternalTransformTest.expansion_service_port or 8091)

      jar = JavaExternalTransformTest.expansion_service_jar
      port = JavaExternalTransformTest.expansion_service_port

      # Start the java server and wait for it to be ready.
      if jar:
        java = subprocess_server.JavaHelper.get_java()
        self._server = subprocess.Popen([java, '-jar', jar, str(port)])

      address = 'localhost:%s' % str(port)

      with grpc.insecure_channel(address) as channel:
        grpc.channel_ready_future(channel).result()

    def __exit__(self, type, value, traceback):
      if self._server:
        self._server.kill()
        self._server = None

  @staticmethod
  def test_java_expansion_dataflow():
    if apiclient is None:
      return

    # This test does not actually running the pipeline in Dataflow. It just
    # tests the translation to a Dataflow job request.

    with patch.object(apiclient.DataflowApplicationClient,
                      'create_job') as mock_create_job:
      with JavaExternalTransformTest._RunWithExpansion():
        pipeline_options = PipelineOptions([
            '--runner=DataflowRunner',
            '--project=dummyproject',
            '--region=some-region1',
            '--experiments=beam_fn_api',
            '--temp_location=gs://dummybucket/'
        ])

        # Run a simple count-filtered-letters pipeline.
        JavaExternalTransformTest.run_pipeline(
            pipeline_options,
            JavaExternalTransformTest.expansion_service_port,
            False)

        mock_args = mock_create_job.call_args_list
        assert mock_args
        args, kwargs = mock_args[0]
        job = args[0]
        job_str = '%s' % job
        assert 'beam:transforms:xlang:filter_less_than_eq' in job_str

  @staticmethod
  def run_pipeline_with_expansion_service(pipeline_options):
    with JavaExternalTransformTest._RunWithExpansion():
      # Run a simple count-filtered-letters pipeline.
      JavaExternalTransformTest.run_pipeline(
          pipeline_options,
          JavaExternalTransformTest.expansion_service_port,
          True)

  @staticmethod
  def run_pipeline(pipeline_options, expansion_service, wait_until_finish=True):
    # The actual definitions of these transforms is in
    # org.apache.beam.sdk.util.construction.TestExpansionService.
    TEST_COUNT_URN = "beam:transforms:xlang:count"
    TEST_FILTER_URN = "beam:transforms:xlang:filter_less_than_eq"

    # Run a simple count-filtered-letters pipeline.
    p = TestPipeline(options=pipeline_options)

    if isinstance(expansion_service, int):
      # Only the port was specified.
      expansion_service = 'localhost:%s' % str(expansion_service)

    res = (
        p
        | beam.Create(list('aaabccxyyzzz'))
        | beam.Map(str)
        | beam.ExternalTransform(
            TEST_FILTER_URN,
            ImplicitSchemaPayloadBuilder({'data': 'middle'}),
            expansion_service)
        | beam.ExternalTransform(TEST_COUNT_URN, None, expansion_service)
        # Map(lambda) produces a label formatted like this, but it cannot be
        # changed without breaking update compat. Here, we pin to the transform
        # name used in the 2.68 release to avoid breaking changes when the line
        # number changes. Context: https://github.com/apache/beam/pull/36381
        | "Map(<lambda at external_java.py:148>)" >>
        beam.Map(lambda kv: '%s: %s' % kv))

    assert_that(res, equal_to(['a: 3', 'b: 1', 'c: 2']))

    result = p.run()
    if wait_until_finish:
      result.wait_until_finish()


if __name__ == '__main__':
  logging.getLogger().setLevel(logging.INFO)
  parser = argparse.ArgumentParser()
  parser.add_argument('--expansion_service_jar')
  parser.add_argument('--expansion_service_port')
  parser.add_argument('--expansion_service_target')
  parser.add_argument('--expansion_service_target_appendix')
  known_args, pipeline_args = parser.parse_known_args(sys.argv)

  if known_args.expansion_service_jar:
    JavaExternalTransformTest.expansion_service_jar = (
        known_args.expansion_service_jar)
    JavaExternalTransformTest.expansion_service_port = int(
        known_args.expansion_service_port)
    pipeline_options = PipelineOptions(pipeline_args)
    JavaExternalTransformTest.run_pipeline_with_expansion_service(
        pipeline_options)
  elif known_args.expansion_service_target:
    pipeline_options = PipelineOptions(pipeline_args)
    JavaExternalTransformTest.run_pipeline(
        pipeline_options,
        beam.transforms.external.BeamJarExpansionService(
            known_args.expansion_service_target,
            gradle_appendix=known_args.expansion_service_target_appendix))
  else:
    raise RuntimeError(
        "--expansion_service_jar or --expansion_service_target "
        "should be provided.")
