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

# pytype: skip-file

import unittest

import hamcrest as hc

import apache_beam as beam
from apache_beam.io.restriction_trackers import OffsetRange
from apache_beam.io.restriction_trackers import OffsetRestrictionTracker
from apache_beam.io.watermark_estimators import ManualWatermarkEstimator
from apache_beam.options.pipeline_options import PipelineOptions
from apache_beam.runners.common import DoFnSignature
from apache_beam.runners.common import PerWindowInvoker
from apache_beam.runners.sdf_utils import SplitResultPrimary
from apache_beam.runners.sdf_utils import SplitResultResidual
from apache_beam.testing.test_pipeline import TestPipeline
from apache_beam.testing.test_stream import TestStream
from apache_beam.transforms import trigger
from apache_beam.transforms import window
from apache_beam.transforms.core import DoFn
from apache_beam.transforms.core import RestrictionProvider
from apache_beam.transforms.window import IntervalWindow
from apache_beam.utils.timestamp import Timestamp
from apache_beam.utils.windowed_value import WindowedValue


class DoFnSignatureTest(unittest.TestCase):
  def test_dofn_validate_process_error(self):
    class MyDoFn(DoFn):
      def process(self, element, w1=DoFn.WindowParam, w2=DoFn.WindowParam):
        pass

    with self.assertRaises(ValueError):
      DoFnSignature(MyDoFn())

  def test_dofn_get_defaults(self):
    class MyDoFn(DoFn):
      def process(self, element, w=DoFn.WindowParam):
        pass

    signature = DoFnSignature(MyDoFn())

    self.assertEqual(signature.process_method.defaults, [DoFn.WindowParam])

  @unittest.skip('BEAM-5878')
  def test_dofn_get_defaults_kwonly(self):
    class MyDoFn(DoFn):
      def process(self, element, *, w=DoFn.WindowParam):
        pass

    signature = DoFnSignature(MyDoFn())

    self.assertEqual(signature.process_method.defaults, [DoFn.WindowParam])

  def test_dofn_validate_start_bundle_error(self):
    class MyDoFn(DoFn):
      def process(self, element):
        pass

      def start_bundle(self, w1=DoFn.WindowParam):
        pass

    with self.assertRaises(ValueError):
      DoFnSignature(MyDoFn())

  def test_dofn_validate_finish_bundle_error(self):
    class MyDoFn(DoFn):
      def process(self, element):
        pass

      def finish_bundle(self, w1=DoFn.WindowParam):
        pass

    with self.assertRaises(ValueError):
      DoFnSignature(MyDoFn())

  def test_unbounded_element_process_fn(self):
    class UnboundedDoFn(DoFn):
      @DoFn.unbounded_per_element()
      def process(self, element):
        pass

    class BoundedDoFn(DoFn):
      def process(self, element):
        pass

    signature = DoFnSignature(UnboundedDoFn())
    self.assertTrue(signature.is_unbounded_per_element())
    signature = DoFnSignature(BoundedDoFn())
    self.assertFalse(signature.is_unbounded_per_element())


class DoFnProcessTest(unittest.TestCase):
  # pylint: disable=expression-not-assigned
  all_records = None

  def setUp(self):
    DoFnProcessTest.all_records = []

  def record_dofn(self):
    class RecordDoFn(DoFn):
      def process(self, element):
        DoFnProcessTest.all_records.append(element)

    return RecordDoFn()

  def test_dofn_process_keyparam(self):
    class DoFnProcessWithKeyparam(DoFn):
      def process(self, element, mykey=DoFn.KeyParam):
        yield "{key}-verify".format(key=mykey)

    pipeline_options = PipelineOptions()

    with TestPipeline(options=pipeline_options) as p:
      test_stream = (TestStream().advance_watermark_to(10).add_elements([1, 2]))
      (
          p
          | test_stream
          | beam.Map(lambda x: (x, "some-value"))
          | "window_into" >> beam.WindowInto(
              window.FixedWindows(5),
              accumulation_mode=trigger.AccumulationMode.DISCARDING)
          | beam.ParDo(DoFnProcessWithKeyparam())
          | beam.ParDo(self.record_dofn()))

    self.assertEqual(['1-verify', '2-verify'],
                     sorted(DoFnProcessTest.all_records))

  def test_dofn_process_keyparam_error_no_key(self):
    class DoFnProcessWithKeyparam(DoFn):
      def process(self, element, mykey=DoFn.KeyParam):
        yield "{key}-verify".format(key=mykey)

    pipeline_options = PipelineOptions()
    with self.assertRaises(ValueError),\
         TestPipeline(options=pipeline_options) as p:
      test_stream = (TestStream().advance_watermark_to(10).add_elements([1, 2]))
      (p | test_stream | beam.ParDo(DoFnProcessWithKeyparam()))

  def test_pardo_with_unbounded_per_element_dofn(self):
    class UnboundedDoFn(beam.DoFn):
      @beam.DoFn.unbounded_per_element()
      def process(self, element):
        pass

    class BoundedDoFn(beam.DoFn):
      def process(self, element):
        pass

    with TestPipeline() as p:
      source = p | beam.Impulse()
      unbounded_pcoll = source | beam.ParDo(UnboundedDoFn())
      bounded_pcoll = source | beam.ParDo(BoundedDoFn())

      self.assertEqual(unbounded_pcoll.is_bounded, False)
      self.assertEqual(bounded_pcoll.is_bounded, True)


class TestOffsetRestrictionProvider(RestrictionProvider):
  def restriction_size(self, element, restriction):
    return restriction.size()


class PerWindowInvokerSplitTest(unittest.TestCase):
  def setUp(self):
    self.window1 = IntervalWindow(0, 10)
    self.window2 = IntervalWindow(10, 20)
    self.window3 = IntervalWindow(20, 30)
    self.windowed_value = WindowedValue(
        'a', 57, (self.window1, self.window2, self.window3))
    self.restriction = OffsetRange(0, 100)
    self.watermark_estimator_state = Timestamp(21)
    self.restriction_provider = TestOffsetRestrictionProvider()
    self.watermark_estimator = ManualWatermarkEstimator(Timestamp(42))
    self.maxDiff = None

  def create_split_in_window(self, offset_index, windows):
    return (
        SplitResultPrimary(
            primary_value=WindowedValue(((
                'a',
                (OffsetRange(0, offset_index), self.watermark_estimator_state)),
                                         offset_index),
                                        57,
                                        windows)),
        SplitResultResidual(
            residual_value=WindowedValue(((
                'a',
                (
                    OffsetRange(offset_index, 100),
                    self.watermark_estimator.get_estimator_state())),
                                          100 - offset_index),
                                         57,
                                         windows),
            current_watermark=self.watermark_estimator.current_watermark(),
            deferred_timestamp=None))

  def create_split_across_windows(self, primary_windows, residual_windows):
    primary = SplitResultPrimary(
        primary_value=WindowedValue(
            (('a', (OffsetRange(0, 100), self.watermark_estimator_state)), 100),
            57,
            primary_windows)) if primary_windows else None
    residual = SplitResultResidual(
        residual_value=WindowedValue(
            (('a', (OffsetRange(0, 100), self.watermark_estimator_state)), 100),
            57,
            residual_windows),
        current_watermark=None,
        deferred_timestamp=None) if residual_windows else None
    return primary, residual

  def test_non_window_observing_checkpoint(self):
    # test checkpoint
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.0,
        None,
        None,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    expected_primary_split, expected_residual_split = (
        self.create_split_in_window(31, self.windowed_value.windows))
    self.assertEqual([expected_primary_split], primaries)
    self.assertEqual([expected_residual_split], residuals)
    # We don't expect the stop index to be set for non window observing splits
    self.assertIsNone(stop_index)

  def test_non_window_observing_split(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.1,
        None,
        None,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    expected_primary_split, expected_residual_split = (
        self.create_split_in_window(37, self.windowed_value.windows))
    self.assertEqual([expected_primary_split], primaries)
    self.assertEqual([expected_residual_split], residuals)
    # We don't expect the stop index to be set for non window observing splits
    self.assertIsNone(stop_index)

  def test_non_window_observing_split_when_restriction_is_done(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(100)
    self.assertIsNone(
        PerWindowInvoker._try_split(
            0.1,
            None,
            None,
            self.windowed_value,
            self.restriction,
            self.watermark_estimator_state,
            self.restriction_provider,
            restriction_tracker,
            self.watermark_estimator))

  def test_window_observing_checkpoint_on_first_window(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.0,
        0,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    expected_primary_split, expected_residual_split = (
        self.create_split_in_window(31, (self.window1, )))
    _, expected_residual_windows = (
        self.create_split_across_windows(None, (self.window2, self.window3,)))
    hc.assert_that(primaries, hc.contains_inanyorder(expected_primary_split))
    hc.assert_that(
        residuals,
        hc.contains_inanyorder(
            expected_residual_split,
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 1)

  def test_window_observing_checkpoint_on_first_window_after_prior_split(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.0,
        0,
        2,  # stop index < len(windows) representing a prior split had occurred
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    expected_primary_split, expected_residual_split = (
        self.create_split_in_window(31, (self.window1, )))
    _, expected_residual_windows = (
        self.create_split_across_windows(None, (self.window2, )))
    hc.assert_that(primaries, hc.contains_inanyorder(expected_primary_split))
    hc.assert_that(
        residuals,
        hc.contains_inanyorder(
            expected_residual_split,
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 1)

  def test_window_observing_split_on_first_window(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.2,
        0,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    # 20% of 2.7 windows = 20% of 270 offset left = 54 offset
    # 30 + 54 = 84 split offset
    expected_primary_split, expected_residual_split = (
        self.create_split_in_window(84, (self.window1, )))
    _, expected_residual_windows = (
        self.create_split_across_windows(None, (self.window2, self.window3, )))
    hc.assert_that(primaries, hc.contains_inanyorder(expected_primary_split))
    hc.assert_that(
        residuals,
        hc.contains_inanyorder(
            expected_residual_split,
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 1)

  def test_window_observing_split_on_middle_window(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.2,
        1,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    # 20% of 1.7 windows = 20% of 170 offset left = 34 offset
    # 30 + 34 = 64 split offset
    expected_primary_split, expected_residual_split = (
        self.create_split_in_window(64, (self.window2, )))
    expected_primary_windows, expected_residual_windows = (
        self.create_split_across_windows((self.window1, ), (self.window3, )))
    hc.assert_that(
        primaries,
        hc.contains_inanyorder(
            expected_primary_split,
            expected_primary_windows,
        ))
    hc.assert_that(
        residuals,
        hc.contains_inanyorder(
            expected_residual_split,
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 2)

  def test_window_observing_split_on_last_window(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.2,
        2,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    # 20% of 0.7 windows = 20% of 70 offset left = 14 offset
    # 30 + 14 = 44 split offset
    expected_primary_split, expected_residual_split = (
        self.create_split_in_window(44, (self.window3, )))
    expected_primary_windows, _ = (
        self.create_split_across_windows((self.window1, self.window2, ), None))
    hc.assert_that(
        primaries,
        hc.contains_inanyorder(
            expected_primary_split,
            expected_primary_windows,
        ))
    hc.assert_that(
        residuals, hc.contains_inanyorder(
            expected_residual_split,
        ))
    self.assertEqual(stop_index, 3)

  def test_window_observing_split_on_first_window_fallback(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(100)
    # We assume that we can't split this fully claimed restriction
    self.assertIsNone(restriction_tracker.try_split(0))
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.0,
        0,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    expected_primary_windows, expected_residual_windows = (
        self.create_split_across_windows(
            (self.window1, ), (self.window2, self.window3, )))
    hc.assert_that(
        primaries, hc.contains_inanyorder(
            expected_primary_windows,
        ))
    hc.assert_that(
        residuals, hc.contains_inanyorder(
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 1)

  def test_window_observing_split_on_middle_window_fallback(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(100)
    # We assume that we can't split this fully claimed restriction
    self.assertIsNone(restriction_tracker.try_split(0))
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.0,
        1,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    expected_primary_windows, expected_residual_windows = (
        self.create_split_across_windows(
            (self.window1, self.window2, ), (self.window3, )))
    hc.assert_that(
        primaries, hc.contains_inanyorder(
            expected_primary_windows,
        ))
    hc.assert_that(
        residuals, hc.contains_inanyorder(
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 2)

  def test_window_observing_split_on_last_window_when_split_not_possible(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(100)
    # We assume that we can't split this fully claimed restriction
    self.assertIsNone(restriction_tracker.try_split(0))
    self.assertIsNone(
        PerWindowInvoker._try_split(
            0.0,
            2,
            3,
            self.windowed_value,
            self.restriction,
            self.watermark_estimator_state,
            self.restriction_provider,
            restriction_tracker,
            self.watermark_estimator))

  def test_window_observing_split_on_window_boundary_round_up(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.6,
        0,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    # 60% of 2.7 windows = 60% of 270 offset left = 162 offset
    # 30 + 162 = 192 offset --> round to end of window 2
    expected_primary_windows, expected_residual_windows = (
        self.create_split_across_windows(
            (self.window1, self.window2, ), (self.window3, )))
    hc.assert_that(
        primaries, hc.contains_inanyorder(
            expected_primary_windows,
        ))
    hc.assert_that(
        residuals, hc.contains_inanyorder(
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 2)

  def test_window_observing_split_on_window_boundary_round_down(self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.3,
        0,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    # 30% of 2.7 windows = 30% of 270 offset left = 81 offset
    # 30 + 81 = 111 offset --> round to end of window 1
    expected_primary_windows, expected_residual_windows = (
        self.create_split_across_windows(
            (self.window1, ), (self.window2, self.window3, )))
    hc.assert_that(
        primaries, hc.contains_inanyorder(
            expected_primary_windows,
        ))
    hc.assert_that(
        residuals, hc.contains_inanyorder(
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 1)

  def test_window_observing_split_on_window_boundary_round_down_on_last_window(
      self):
    restriction_tracker = OffsetRestrictionTracker(self.restriction)
    restriction_tracker.try_claim(30)
    (primaries, residuals, stop_index) = PerWindowInvoker._try_split(
        0.9,
        0,
        3,
        self.windowed_value,
        self.restriction,
        self.watermark_estimator_state,
        self.restriction_provider,
        restriction_tracker,
        self.watermark_estimator)
    # 90% of 2.7 windows = 90% of 270 offset left = 243 offset
    # 30 + 243 = 273 offset --> prefer a split so round to end of window 2
    # instead of no split
    expected_primary_windows, expected_residual_windows = (
        self.create_split_across_windows(
            (self.window1, self.window2, ), (self.window3, )))
    hc.assert_that(
        primaries, hc.contains_inanyorder(
            expected_primary_windows,
        ))
    hc.assert_that(
        residuals, hc.contains_inanyorder(
            expected_residual_windows,
        ))
    self.assertEqual(stop_index, 2)


if __name__ == '__main__':
  unittest.main()
