/**
 * 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 React, { useState } from 'react';
import { Pressable, StyleSheet, View } from 'react-native';
import { TestCase, TestSuite } from '@rnoh/testerino';

export function PressableTest() {
  return (
    <TestSuite name="Pressable">
      <TestCase
        itShould="handle short presses"
        initialState={{
          onPressIn: false,
          onPress: false,
        }}
        arrange={({ setState }) => {
          return (
            <Pressable
              onPressIn={() => setState(prev => ({ ...prev, onPressIn: true }))}
              onPress={() => setState(prev => ({ ...prev, onPress: true }))}>
              <View style={styles.unpressed} />
            </Pressable>
          );
        }}
        assert={({ expect, state }) => {
          expect(state).to.be.deep.eq({
            onPressIn: true,
            onPress: true,
          });
        }}
      />
      <TestCase
        itShould="handle long press"
        initialState={{
          onLongPress: false,
        }}
        arrange={({ setState }) => {
          return (
            <Pressable onLongPress={() => setState({ onLongPress: true })}>
              <View style={styles.unpressed} />
            </Pressable>
          );
        }}
        assert={({ expect, state }) => {
          expect(state).to.be.deep.eq({
            onLongPress: true,
          });
        }}
      />
      <TestCase
        itShould="handle pressing out"
        initialState={{
          onPressOut: false,
        }}
        arrange={({ setState }) => {
          return (
            <Pressable onPressOut={() => setState({ onPressOut: true })}>
              <View style={styles.unpressed} />
            </Pressable>
          );
        }}
        assert={({ expect, state }) => {
          expect(state).to.be.deep.eq({
            onPressOut: true,
          });
        }}
      />
      <TestCase
        itShould="inner view should not react to presses"
        initialState={{
          tested: false,
          pressed: false,
        }}
        arrange={({ setState }) => {
          return (
            <Pressable
              onPress={() => setState(prev => ({ ...prev, tested: true }))}
              style={styles.pressed}>
              <Pressable
                onPress={() => setState(prev => ({ ...prev, pressed: true }))}
                style={styles.unpressed}
                disabled
              />
            </Pressable>
          );
        }}
        assert={({ expect, state }) => {
          expect(state).to.be.deep.eq({
            tested: true,
            pressed: false,
          });
        }}
      />
      <TestCase
        itShould="change color to blue on hover"
        skip
      //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/417
      >
        <HoverView />
      </TestCase>
      <TestCase
        itShould="pass when blue background is pressed"
        initialState={false}
        arrange={({ setState }) => (
          <View
            style={{
              backgroundColor: 'blue',
              alignSelf: 'center',
              position: 'relative',
            }}>
            <Pressable
              hitSlop={{ top: 48, left: 48, bottom: 48, right: 48 }}
              style={{
                width: 48,
                height: 48,
                backgroundColor: 'green',
                margin: 48,
              }}
              onPress={() => {
                setState(true);
              }}
            />
            <View
              style={{
                width: 48,
                height: 48,
                backgroundColor: 'red',
                position: 'absolute',
                top: 48,
                left: 48,
              }}
              onTouchEnd={e => {
                e.stopPropagation();
              }}
            />
          </View>
        )}
        assert={({ expect, state }) => {
          expect(state).to.be.true;
        }}
      />
    </TestSuite>
  );
}

const HoverView = () => {
  const [hovered, setHovered] = useState(false);
  return (
    <Pressable
      onHoverIn={() => {
        setHovered(true);
      }}
      onHoverOut={() => {
        setHovered(false);
      }}
      style={{ ...styles.unpressed, backgroundColor: hovered ? 'blue' : 'red' }}
    />
  );
};

const styles = StyleSheet.create({
  unpressed: {
    width: 50,
    height: 50,
    backgroundColor: 'red',
  },
  pressed: {
    width: 100,
    height: 100,
    backgroundColor: 'blue',
    justifyContent: 'center',
    alignItems: 'center',
  },
  longPressed: {
    width: 300,
    height: 100,
    backgroundColor: 'green',
  },
  text: {
    height: 20,
    width: 200,
    fontSize: 14,
  },
});