/* Dependencies */
import React, { useState } from 'react'
import {
	KeyboardTypeOptions,
	StyleProp,
	StyleSheet,
	TextStyle
} from 'react-native'

/* Libraries */
import { TextInput, useTheme } from 'react-native-paper'

/* Functions */
import { Circle } from '../Loader'
import { delayedAlert } from '../../functions'
import { backendRequest } from '../../functions/services'

/* Types */
interface Props<T> {
	/**
	 * @description If true, the text input will be disabled
	 * @default false
	 */
	disabled?: boolean
	error?: boolean
	field: string
	label: string
	margin?: number
	navigation: any
	/**
	 * @description Function to be called when the text changes
	 */
	onChange?: (value: string) => void
	onSelect?: (value: T | null) => void
	params?: { [key: string]: number | string }
	process: string
	readOnly?: boolean
	requires?: boolean | string
	requiresMessage?: string
	rootScreen?: string
	screen: string
	setField: React.Dispatch<React.SetStateAction<string>>
	style?: StyleProp<TextStyle>
	/**
	 * @description Keyboard type
	 * @default 'numeric'
	 */
	type?: KeyboardTypeOptions
}

function ViewOnline<T>({
	disabled = false,
	error,
	field,
	label,
	navigation,
	onChange,
	onSelect,
	params = {},
	process,
	readOnly,
	requires,
	requiresMessage = 'Os pré-requisitos não foram atendidos',
	rootScreen,
	screen,
	setField,
	style,
	type = 'numeric'
}: Props<T>) {
	/* Styles */
	const { colors } = useTheme()
	const styles = StyleSheet.create({
		container: {
			flex: 1,
			margin: 5
		}
	})

	/* States */
	const [isFocused, setIsFocused] = useState(false)
	const [visible, setVisible] = useState(false)

	/* Functions */
	async function onBlur(): Promise<void> {
		if (field) {
			if (requires === undefined || requires) {
				setVisible(true)
				try {
					const content = await backendRequest(process, params)
					setField(content ? content.ret : '')
					onSelect?.(content ? content.ret : null)
				} finally {
					setVisible(false)
				}
			} else {
				setField('')
				onSelect?.(null)
				delayedAlert(requiresMessage)
			}
		}
		setIsFocused(false)
	}

	function onChangeText(value: string): void {
		setField(value)
		onChange?.(value)
	}

	function onOpen(): void {
		if (screen) {
			if (requires === undefined || requires) {
				navigation.navigate(screen, {
					root: rootScreen,
					field: label,
					params: params
				})
			} else {
				delayedAlert(requiresMessage)
			}
		} else {
			delayedAlert('Visualização não selecionada')
		}
	}

	return (
		<>
			<Circle visible={visible} />
			<TextInput
				autoCompleteType={'off'}
				editable={readOnly}
				error={error}
				disabled={disabled}
				keyboardType={type}
				label={label}
				mode={'flat'}
				onBlur={() => onBlur()}
				onChangeText={onChangeText}
				onFocus={() => setIsFocused(true)}
				right={
					disabled ? null : (
						<TextInput.Icon
							hasTVPreferredFocus={undefined} // TODO: Fix this
							tvParallaxProperties={undefined} // TODO: Fix this
							color={isFocused ? colors.primary : 'rgb(100,100,100)'}
							name={field ? 'close' : 'magnify'}
							onPress={() => (field ? onChangeText('') : onOpen())}
							size={28}
						/>
					)
				}
				style={style ?? styles.container}
				value={field}
			/>
		</>
	)
}

ViewOnline.displayName = 'Edit.View.Online'

export default ViewOnline
