/**
 * 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, StyleSheet, View } from 'react-native';
import React from 'react';
import { COMMON_PROPS, getScrollViewContent } from './fixtures';
import { useEffect, useRef, useState } from 'react';
import { Button, ObjectDisplayer } from '../../components';

export function MiscPropsTest() {
  return (
    <TestSuite name="misc props">
      <TestCase
        modal
        itShould="scroll should be disabled (it renders with the 5th element at the top)">
        <View style={styles.wrapperView}>
          <ScrollView {...COMMON_PROPS} scrollEnabled={false} />
        </View>
      </TestCase>
      <TestCase modal itShould="display horizontal scroll view">
        <View
          style={{
            width: '100%',
            height: 150,
          }}>
          <ScrollView {...COMMON_PROPS} horizontal={true} />
        </View>
      </TestCase>
      <TestCase
        modal
        itShould="display ScrollView with the third view at the top (contentOffset)"
      //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/305
      >
        <ContentOffsetTestCase />
      </TestCase>
      <TestCase
        modal
        itShould="scroll when contentOffset property is changed (contentOffset)"
      //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/305
      >
        <ToggleContentOffsetTestCase />
      </TestCase>
      <TestCase
        modal
        itShould="toggle backface visibility on button press (the component should become invisible)">
        <BackfaceVisibilityTestCase />
      </TestCase>
      <TestCase
        modal
        skip={Platform.select({ android: 'fails', harmony: 'fails on Android' })}
        itShould="display ScrollView with different contentInsets (contentInset)"
      //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/304
      >
        <View style={styles.wrapperView}>
          <ScrollView
            {...COMMON_PROPS}
            contentInset={{ top: 10, right: 20, bottom: 30, left: 40 }}
          />
        </View>
      </TestCase>
      <TestCase
        modal
        itShould="display current contentHeight (onContentSizeChange)">
        <OnContentSizeChangeTestCase />
      </TestCase>
      <TestCase
        modal
        itShould="display onScroll native event throttled every second">
        <ObjectDisplayer
          renderContent={setObject => {
            return (
              <ScrollView
                {...COMMON_PROPS}
                scrollEventThrottle={1000}
                onScroll={(e: { nativeEvent: Object }) => {
                  setObject(e.nativeEvent);
                }}
              />
            );
          }}
        />
      </TestCase>
      <TestCase
        modal
        itShould="the left scrollview should decelerate faster (stops earlier) than the right one (decelarationRate)">
        <View style={[styles.wrapperView, { flexDirection: 'row' }]}>
          <ScrollView {...COMMON_PROPS} decelerationRate={0.8} />
          <ScrollView {...COMMON_PROPS} decelerationRate={0.999} />
        </View>
      </TestCase>

      <TestCase
        modal
        itShould="the left scrollview should bounce (briefly scroll beyond the content to show the view below and then come back to top/bottom accordingly)">
        <View style={[styles.wrapperView, { flexDirection: 'row' }]}>
          <ScrollView {...COMMON_PROPS} />
          <ScrollView {...COMMON_PROPS} bounces={false} />
        </View>
      </TestCase>
      <TestCase
        modal
        skip={Platform.select({ android: 'fails', harmony: 'fails on Android' })}
        itShould="scroll outside of the content when pressing the button (scrollToOverflowEnabled)"
      //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/315
      >
        <ScrollToOverflowEnabledTestCase />
      </TestCase>
      <TestCase
        modal
        skip
        itShould="the left scrollview should allow for nested scroll while the right one shouldn't (nestedScrollEnabled)"
      //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/312
      >
        <View
          style={[
            styles.wrapperView,
            { flexDirection: 'row', alignContent: 'space-between' },
          ]}>
          <ScrollView {...COMMON_PROPS}>
            <ScrollView
              nestedScrollEnabled
              style={{
                width: '70%',
                height: 200,
                borderColor: 'firebrick',
                borderWidth: 2,
              }}>
              {getScrollViewContent({
                style: { backgroundColor: 'green' },
                amountOfChildren: 5,
              })}
            </ScrollView>
            {getScrollViewContent({})}
          </ScrollView>
          <ScrollView {...COMMON_PROPS}>
            <ScrollView
              nestedScrollEnabled={false}
              style={{
                width: '70%',
                height: 200,
                borderColor: 'firebrick',
                borderWidth: 2,
              }}>
              {getScrollViewContent({
                style: { backgroundColor: 'green' },
                amountOfChildren: 5,
              })}
            </ScrollView>
            {getScrollViewContent({})}
          </ScrollView>
        </View>
      </TestCase>
      <TestCase
        modal
        itShould="scroll down on the btn press, but prevent scrolling by dragging (scrollEnabled)">
        <ScrollEnabledTestCase />
      </TestCase>
      <TestCase
        modal
        skip // https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/499
        itShould="render scroll view with different fading edge length (fadingEdgeLength)">
        <ScrollViewFadingEdgeLengthTest />
      </TestCase>
    </TestSuite>
  );
}

function ScrollEnabledTestCase() {
  const scrollRef = React.useRef<ScrollView>(null);
  return (
    <View style={styles.wrapperView}>
      <Button
        label={'Scroll To offset y 150'}
        onPress={() => {
          scrollRef.current?.scrollTo({ x: 0, y: 150, animated: false });
        }}
      />
      <ScrollView style={{ flex: 1 }} scrollEnabled={false} ref={scrollRef}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function ScrollToOverflowEnabledTestCase() {
  const ref = useRef<ScrollView>(null);
  return (
    <View style={styles.wrapperView}>
      <Button
        label={'Scroll outside of the content'}
        onPress={() => {
          ref.current?.scrollTo({ x: 0, y: -60, animated: true });
        }}
      />
      <ScrollView scrollToOverflowEnabled={true} ref={ref}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}
function OnContentSizeChangeTestCase() {
  const [amountOfChildren, setAmountOfChildren] = useState(3);
  return (
    <ObjectDisplayer
      renderContent={setObject => {
        return (
          <View style={{ width: '100%', height: '70%' }}>
            <Button
              label={'Add one more item'}
              onPress={() => {
                setAmountOfChildren(amountOfChildren + 1);
              }}
            />
            <ScrollView
              onContentSizeChange={(_, contentHeight) => {
                setObject({ contentHeight });
              }}>
              {getScrollViewContent({ amountOfChildren: amountOfChildren })}
            </ScrollView>
          </View>
        );
      }}
    />
  );
}

function ContentOffsetTestCase() {
  return (
    <View style={styles.wrapperView}>
      <ScrollView
        style={{
          ...styles.wrapperView,
        }}
        contentOffset={{ x: 0, y: 100 }}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function ToggleContentOffsetTestCase() {
  const [contentOffset, setContentOffset] = useState(100);
  useEffect(() => {
    const id = setInterval(() => {
      setContentOffset(prev => (prev + 50) % 200);
    }, 1000);
    return () => {
      clearInterval(id);
    };
  }, []);

  return (
    <View style={styles.wrapperView}>
      <ScrollView
        style={{
          ...styles.wrapperView,
        }}
        contentOffset={{ x: 0, y: contentOffset }}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function BackfaceVisibilityTestCase() {
  const [backfaceVisibility, setBackfaceVisibility] = useState(true);

  return (
    <View style={styles.wrapperView}>
      <Button
        label={`Make backface ${backfaceVisibility ? 'invisible' : 'visible'}`}
        onPress={() => {
          setBackfaceVisibility(!backfaceVisibility);
        }}
      />
      <ScrollView
        style={{
          ...styles.wrapperView,
          backfaceVisibility: backfaceVisibility ? 'visible' : 'hidden',
          transform: [{ rotateX: '180deg' }],
        }}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function ScrollViewFadingEdgeLengthTest() {
  return (
    <View
      style={{
        width: '100%',
        justifyContent: 'center',
        backgroundColor: 'blue',
      }}>
      <View
        style={{
          height: 400,
          marginTop: 50,
          marginBottom: 50,
        }}>
        <ScrollView fadingEdgeLength={100}>
          {getScrollViewContent({})}
        </ScrollView>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  wrapperView: {
    height: 300,
    width: '60%',
  },
});