/**

 * Copyright (c) 2024 Huawei Technologies Co., Ltd.

 *

 * This source code is licensed under the MIT license found in the

 * LICENSE-MIT file in the root directory of this source tree.

 */



import { TestCase, TestSuite } from '@rnoh/testerino';

import { Platform, ScrollView, View } from 'react-native';

import { getScrollViewContent } from './fixtures';

import { Button } from '../../components';



export function PointerEventsTest() {

  return (

    <TestSuite name="pointer events">

      <TestCase

        itShould="call inner and outer view when pressing inner"

        initialState={{ inner: false, outer: false, outerContainer: false }}

        arrange={({ setState, reset }) => {

          return (

            <PointerEventsView

              pointerEventsOuter="auto"

              setState={setState}

              reset={reset}

            />

          );

        }}

        assert={({ expect, state }) => {

          expect(state).to.be.deep.eq({

            inner: true,

            outer: true,

            outerContainer: true,

          });

        }}

      />

      <TestCase

        //it seems there's a bug on Android, which causes pointerEvents to not work correctly for ScrollViews

        skip={Platform.select({

          android: 'known bug',

          harmony: 'fails on Android',

        })} // https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/424

        itShould="call only outer when pressing inner view"

        initialState={{ inner: false, outer: false, outerContainer: true }}

        arrange={({ setState, reset }) => {

          return (

            <PointerEventsView

              pointerEventsOuter="box-only"

              setState={setState}

              reset={reset}

            />

          );

        }}

        assert={({ expect, state }) => {

          expect(state).to.be.deep.eq({

            inner: false,

            outer: true,

            outerContainer: true,

          });

        }}

      />

      <TestCase

        //it seems there's a bug on Android, which causes pointerEvents to not work correctly for ScrollViews

        skip={Platform.select({

          android: 'known bug',

        })}

        itShould="call inner and outer only when pressing inner view"

        initialState={{ inner: false, outer: false, outerContainer: false }}

        arrange={({ setState, reset }) => {

          return (

            <PointerEventsView

              disableOuterContainerTouch

              pointerEventsOuter="box-none"

              setState={setState}

              reset={reset}

            />

          );

        }}

        assert={({ expect, state }) => {

          expect(state.inner).to.be.true;

          expect(state.outer).to.be.true;

        }}

      />

      <TestCase

        //it seems there's a bug on Android, which causes pointerEvents to not work correctly for ScrollViews

        skip={Platform.select({

          android: 'known bug',

        })}

        itShould="not call inner or outer when pressing inner or outer views"

        initialState={{ inner: false, outer: false, outerContainer: false }}

        arrange={({ setState, reset }) => {

          return (

            <PointerEventsView

              pointerEventsOuter="none"

              setState={setState}

              reset={reset}

            />

          );

        }}

        assert={({ expect, state }) => {

          expect(state).to.be.deep.eq({

            inner: false,

            outer: false,

            outerContainer: true,

          });

        }}

      />

    </TestSuite>

  );

}



function PointerEventsView(props: {

  disableOuterContainerTouch?: boolean;

  pointerEventsOuter?: 'box-none' | 'none' | 'box-only' | 'auto';

  pointerEventsInner?: 'box-none' | 'none' | 'box-only' | 'auto';

  setState: React.Dispatch<

    React.SetStateAction<{

      inner: boolean;

      outer: boolean;

      outerContainer: boolean;

    }>

  >;

  reset: () => void;

}) {

  return (

    <View style={{ height: 100, width: '100%', flexDirection: 'row' }}>

      <View

        style={{ backgroundColor: 'red' }}

        onTouchEnd={

          props.disableOuterContainerTouch

            ? undefined

            : () => {

              props.setState(prev => ({ ...prev, outerContainer: true }));

            }

        }>

        <ScrollView

          nestedScrollEnabled

          style={{

            height: 100,

            width: 100,

            backgroundColor: 'green',

            padding: 20,

          }}

          pointerEvents={props.pointerEventsOuter}

          onTouchEnd={() => {

            props.setState(prev => ({ ...prev, outer: true }));

          }}>

          {getScrollViewContent({

            amountOfChildren: 3,

            onTouchEnd: () => {

              props.setState(prev => ({ ...prev, inner: true }));

            },

            pointerEvents: props.pointerEventsInner,

          })}

        </ScrollView>

      </View>

      <Button label="reset" onPress={props.reset} />

    </View>

  );

}