import { PropTypes } from 'prop-types';
import React, { Component } from 'react';
import { Animated, Dimensions, Keyboard, StyleSheet, TextInput, UIManager } from 'react-native';

const { State: TextInputState } = TextInput;

const styles = StyleSheet.create({
	container: {
		height: '100%',
		left: 0,
		position: 'absolute',
		top: 0,
		width: '100%',
	},
});

export default class KeyboardShift extends Component {
	constructor(props) {
		super(props);
		this.state = {
			shift: new Animated.Value(0),
		};
	}

	componentDidMount() {
		this.keyboardDidShowSub = Keyboard.addListener('keyboardDidShow', this.handleKeyboardDidShow);
		this.keyboardDidHideSub = Keyboard.addListener('keyboardDidHide', this.handleKeyboardDidHide);
	}

	componentWillUnmount() {
		this.keyboardDidShowSub.remove();
		this.keyboardDidHideSub.remove();
	}

	handleKeyboardDidShow = (event) => {
		const { height: windowHeight } = Dimensions.get('window');
		const keyboardHeight = event.endCoordinates.height;
		const currentlyFocusedField = TextInputState.currentlyFocusedField();
		UIManager.measure(currentlyFocusedField, (originX, originY, width, height, pageX, pageY) => {
			const fieldHeight = height;
			const fieldTop = pageY + 50;
			const gap = (windowHeight - keyboardHeight) - (fieldTop + fieldHeight);
			if (gap >= 0) {
				return;
			}
			Animated.timing(
				this.state.shift,
				{
					toValue: gap,
					duration: 0,
					useNativeDriver: true,
				},
			).start();
		});
	}

	handleKeyboardDidHide = () => {
		Animated.timing(
			this.state.shift,
			{
				toValue: 0,
				duration: 0,
				useNativeDriver: true,
			},
		).start();
	}

	render() {
		const { children } = this.props;
		const { shift } = this.state;
		return (
			<Animated.View
				style={[
					styles.container, {
						transform: [
							{
								translateY: shift,
							},
						],
					}]}
			>
				{React.Children.map(children, (child) => (child))}
			</Animated.View>
		);
	}
}

KeyboardShift.propTypes = {
	children: PropTypes.any,
};
KeyboardShift.defaultProps = {
	children: null,
};
