import React, { useState, useRef } from 'react'
import {
	View,
	ActivityIndicator as Spinner,
	KeyboardAvoidingView,
	Text,
	TextInput,
	TouchableHighlight,
	TouchableOpacity,
	ViewStyle,
	Switch,
	Vibration,
} from 'react-native'
import { useLayout } from '@react-native-community/hooks'
import { Translation } from 'react-i18next'
import Swiper from 'react-native-swiper'
import { Card, TouchableCard } from './shared-components/Card'
import { useStyles } from '@berty-tech/styles'
import { useNavigation, Routes } from '@berty-tech/navigation'
import { Messenger } from '@berty-tech/store/oldhooks'
import { useNavigation as useReactNavigation, CommonActions } from '@react-navigation/native'
import { useDispatch } from 'react-redux'
import { useMsgrContext } from '@berty-tech/store/context'
import messengerMethodsHooks from '@berty-tech/store/methods'

import { SafeAreaView } from 'react-native-safe-area-context'
import Logo from './berty_gradient_square.svg'
import LottieView from 'lottie-react-native'

type Navigation = () => void
type Form<T> = (arg0: T) => Promise<void>

const Button: React.FC<{
	children: string
	onPress: () => Promise<void> | void
	style?: ViewStyle
}> = ({ children, onPress, style = null }) => {
	const [{ margin, padding, background, color, text, border }] = useStyles()
	const [loading, setLoading] = React.useState(false)
	return (
		<TouchableHighlight
			style={[
				padding.horizontal.big,
				margin.top.medium,
				padding.medium,
				loading ? background.light.blue : background.blue,
				border.radius.small,
				style,
			]}
			underlayColor={color.light.blue}
			onPress={async () => {
				try {
					setLoading(true)
					await onPress()
				} finally {
					setLoading(false)
				}
			}}
		>
			{loading ? (
				<Spinner style={[text.size.medium]} color={color.white} />
			) : (
				<Text style={[text.size.medium, text.color.white, text.align.center, text.bold.medium]}>
					{children}
				</Text>
			)}
		</TouchableHighlight>
	)
}

export const GetStarted: React.FC = () => {
	const { navigate } = useNavigation()
	const [{ absolute, background, column, flex, padding, text }] = useStyles()
	return (
		<Translation>
			{(t) => (
				<SafeAreaView style={[absolute.fill, background.white, column.justify, padding.medium]}>
					<View style={[flex.medium]} />
					<View style={[flex.big, { flexDirection: 'row', justifyContent: 'center' }]}>
						<Logo height='60%' width='65%' />
					</View>
					<View style={[flex.medium]}>
						<Text style={[padding.horizontal.medium, text.align.center, text.align.bottom]}>
							{t('onboarding.getstarted')}
						</Text>
					</View>
					<View style={[flex.medium]}>
						<Button style={column.item.center} onPress={navigate.onboarding.performance}>
							GET STARTED
						</Button>
					</View>
				</SafeAreaView>
			)}
		</Translation>
	)
}

export const SelectMode: React.FC = () => {
	const { navigate } = useNavigation()
	const [{ flex, absolute, background, column, padding, text, margin }] = useStyles()
	return (
		<Translation>
			{(t) => (
				<SafeAreaView style={[absolute.fill, background.white]}>
					<Text
						style={[
							text.align.center,
							text.align.justify,
							text.size.huge,
							padding.top.huge,
							text.bold.medium,
						]}
					>
						Select your app mode
					</Text>
					<TouchableCard
						style={[
							background.blue,
							column.fill,
							margin.top.huge,
							margin.horizontal.huge,
							flex.medium,
							column.justify,
						]}
						onPress={() => navigate.onboarding.performance()}
					>
						<Text style={[text.bold.medium, text.size.big, text.color.white, text.align.justify]}>
							{t('onboarding.select-mode.performance.title')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.performance.desc')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.performance.push-notif')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.performance.offline-message')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.performance.add-contact')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.performance.fast-message')}
						</Text>
					</TouchableCard>
					<TouchableCard
						style={[background.red, column.fill, margin.huge, flex.medium, column.justify]}
						onPress={() => navigate.onboarding.privacy()}
					>
						<Text style={[text.bold.medium, text.size.big, text.color.white]}>
							{t('onboarding.select-mode.high-level.title')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.high-level.desc')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.high-level.disable-push-notif')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.high-level.disable-local-peer-discovery')}
						</Text>
						<Text style={[text.size.medium, text.color.white]}>
							{t('onboarding.select-mode.high-level.disable-contact-request')}
						</Text>
					</TouchableCard>
					<Text style={[text.size.tiny, flex.tiny, column.fill, text.align.center]}>
						All this presets can be modified at any time in the settings
					</Text>
				</SafeAreaView>
			)}
		</Translation>
	)
}

const SwiperCard: React.FC<{
	label?: 'required' | 'optional' | 'recommended' | ''
	header?: string
	title: string
	description: string
	button?: { text: string; onPress: () => Promise<void> | void }
	skip?: { text: string; onPress: () => void }
}> = ({ children, header, label, title, description, button, skip }) => {
	const [{ absolute, text, padding, margin, background, border, column }] = useStyles()
	let labelColor: keyof typeof background.light
	switch (label) {
		default:
			labelColor = 'white'
			break
		case 'required':
			labelColor = 'red'
			break
		case 'optional':
			labelColor = 'yellow'
			break
		case 'recommended':
			labelColor = 'green'
			break
	}
	return (
		<SafeAreaView style={[margin.bottom.huge, absolute.fill]}>
			<Text
				style={[
					absolute.fill,
					margin.big,
					padding.vertical.big,
					text.size.large,
					text.color.white,
					text.align.center,
				]}
			>
				{header}
			</Text>
			<Card
				style={[
					background.white,
					absolute.bottom,
					absolute.left,
					absolute.right,
					border.shadow.large,
				]}
			>
				<View
					style={[
						padding.tiny,
						column.item.right,
						background.light[labelColor],
						border.radius.tiny,
					]}
				>
					{label ? (
						<Text style={[text.size.small, text.color[labelColor], text.align.right]}>{label}</Text>
					) : null}
				</View>
				<Text
					style={[
						text.size.huge,
						padding.top.medium,
						text.align.center,
						text.bold.medium,
						text.color.blue,
					]}
				>
					{title}
				</Text>
				<Text
					style={[text.size.medium, padding.vertical.medium, text.align.center, text.color.grey]}
				>
					{description}
				</Text>
				{children}
				{button ? <Button onPress={button.onPress}>{button.text}</Button> : null}
				{skip ? (
					<TouchableOpacity style={[margin.top.medium]} onPress={skip.onPress}>
						<Text style={[text.size.small, text.color.grey, text.align.center]}>{skip.text}</Text>
					</TouchableOpacity>
				) : null}
			</Card>
		</SafeAreaView>
	)
}

const defaultEmbeddedConfig = {
	type: 'embedded',
	// opts: protocol.client.defaultBridgeOpts,
}

const NodeConfigInput: React.FC<{
	config: any
	onConfigChange: (config: any) => void
}> = ({ config, onConfigChange }) => {
	return <Text>TODO</Text>
	const [{ text, padding, margin, background, border }] = useStyles()
	const toggleNodeType = () =>
		onConfigChange(
			config.type === 'external'
				? defaultEmbeddedConfig
				: /*protocol.client.defaultExternalBridgeConfig*/ undefined,
		)
	let content: Element
	if (config.type === 'external') {
		content = (
			<>
				<TextInput
					placeholder={'Bridge port'}
					style={[
						margin.top.medium,
						background.light.grey,
						padding.medium,
						text.size.large,
						border.radius.small,
						text.color.black,
					]}
					value={`${config.port}`}
					onChangeText={(text) => onConfigChange({ ...config, port: parseInt(text, 10) })}
				/>
			</>
		)
	} else {
		content = (
			<>
				<View style={{ flexDirection: 'row', alignItems: 'center' }}>
					<Text>Persist: </Text>
					<Switch
						value={config.opts.persistence}
						onValueChange={() =>
							onConfigChange({
								...config,
								opts: { ...config.opts, persistence: !config.opts.persistence },
							})
						}
					/>
				</View>
				<View style={{ flexDirection: 'row', alignItems: 'center' }}>
					<Text>Trace: </Text>
					<Switch
						value={config.opts.tracing}
						onValueChange={() =>
							onConfigChange({
								...config,
								opts: { ...config.opts, tracing: !config.opts.tracing },
							})
						}
					/>
				</View>
			</>
		)
	}
	return (
		<>
			<View style={{ flexDirection: 'row', alignItems: 'center' }}>
				<Switch value={config.type === 'external'} onValueChange={toggleNodeType} />
				<Text> {config.type}</Text>
			</View>
			{content}
		</>
	)
}

const CreateYourAccount: React.FC<{
	next: Navigation
	onCreate: () => void
}> = ({ next, onCreate }) => {
	const ctx: any = useMsgrContext()
	const [{ text, padding, margin, background, border }] = useStyles()
	const [name, setName] = React.useState('')
	const [error, setError] = React.useState()
	const [isPressed, setIsPressed] = useState<boolean>(false)
	const onPress = React.useCallback(() => {
		const displayName = name || `anon#${ctx.account.publicKey.substr(0, 4)}`
		ctx.client
			.accountUpdate({ displayName })
			.then(() => {
				// TODO: check that account is in "ready" state
				setIsPressed(true)
			})
			.catch((err: any) => setError(err))
	}, [ctx.client, ctx.account.publicKey, name])
	return (
		<Translation>
			{(t) => (
				<>
					<View style={{ flex: 1 }}>
						<LottieView
							source={require('./Berty_onboard_animation_assets2/Startup animation assets/Berty BG.json')}
							autoPlay
							loop
							style={{ width: '100%' }}
						/>

						{!isPressed ? (
							<LottieView
								source={require('./Berty_onboard_animation_assets2/Startup animation assets/Shield appear.json')}
								autoPlay
								loop={false}
							/>
						) : (
							<LottieView
								source={require('./Berty_onboard_animation_assets2/Startup animation assets/Shield dissapear.json')}
								autoPlay
								loop={false}
								onAnimationFinish={async (): Promise<void> => {
									//createAccount({ name: name || 'Anonymous 1337', nodeConfig })
									Vibration.vibrate(500)
									onCreate()
									// @TODO: Error handling
									next()
								}}
							/>
						)}
					</View>
					<View style={{ flex: 1 }}>
						<SwiperCard
							label='required'
							title={t('onboarding.create-account.required')}
							description={t('onboarding.create-account.desc')}
							button={{
								text: t('onboarding.create-account.button'),
								onPress,
							}}
						>
							<TextInput
								autoCapitalize='none'
								autoCorrect={false}
								value={name}
								onChangeText={setName}
								placeholder={t('onboarding.create-account.placeholder')}
								style={[
									margin.top.medium,
									background.light.grey,
									padding.medium,
									text.size.large,
									border.radius.small,
									text.color.black,
								]}
							/>
							{__DEV__ && <NodeConfigInput onConfigChange={() => {}} config={{}} />}
							{error && <Text>{error.toString()}</Text>}
						</SwiperCard>
					</View>
				</>
			)}
		</Translation>
	)
}

const Notifications: React.FC<{
	submit: Form<{}>
	next: Navigation
}> = ({ submit, next }) => (
	<Translation>
		{(t) => (
			<SwiperCard
				header={t('onboarding.notifications.header')}
				label={t('onboarding.notifications.recommended')}
				title={t('onboarding.notifications.title')}
				description={t('onboarding.notifications.desc')}
				button={{
					text: t('onboarding.notifications.button'),
					onPress: async (): Promise<void> => {
						try {
							await submit({})
							Vibration.vibrate(500)
							next()
						} catch (err) {
							next()
						}
					},
				}}
				skip={{
					text: t('onboarding.notifications.skip'),
					onPress: next,
				}}
			/>
		)}
	</Translation>
)

const Bluetooth: React.FC<{
	submit: Form<{}>
	next: Navigation
}> = ({ submit, next }) => (
	<Translation>
		{(t) => (
			<SwiperCard
				header={t('onboarding.bluetooth.header')}
				label={t('onboarding.bluetooth.optional')}
				title={t('onboarding.bluetooth.title')}
				description={t('onboarding.bluetooth.desc')}
				button={{
					text: t('onboarding.bluetooth.button'),
					onPress: async (): Promise<void> => {
						try {
							await submit({})
							Vibration.vibrate(500)
							next()
						} catch (err) {
							next()
						}
					},
				}}
				skip={{
					text: t('onboarding.bluetooth.skip'),
					onPress: next,
				}}
			/>
		)}
	</Translation>
)

const SetupFinished: React.FC = () => {
	const navigation = useReactNavigation()
	//const client = Messenger.useClient()
	//const dispatch = useDispatch()
	const [isGeneration, setIsGeneration] = useState<number>(1)
	const [isGenerated, setIsGenerated] = useState<boolean>(false)
	const [isFinished, setIsFinished] = useState<boolean>(false)
	const [isAccount, setIsAccount] = useState<boolean>(false)
	const client = {}
	return (
		<Translation>
			{(t) =>
				isAccount ? (
					<>
						<View style={{ flex: 1 }}>
							<LottieView
								source={require('./Berty_onboard_animation_assets2/Startup animation assets/Berty BG.json')}
								autoPlay
								loop
								style={{ width: '100%' }}
							/>
							{!isGenerated ? (
								<>
									<LottieView
										source={require('./Berty_onboard_animation_assets2/Startup animation assets/Circle spin.json')}
										autoPlay
										loop={false}
									/>
									<LottieView
										source={require('./Berty_onboard_animation_assets2/Startup animation assets/Code Generated.json')}
										autoPlay
										loop={false}
										onAnimationFinish={() => {
											setIsGenerated(true)
										}}
									/>
								</>
							) : (
								<>
									{!isFinished ? (
										<LottieView
											source={require('./Berty_onboard_animation_assets2/Startup animation assets/Finish appear.json')}
											autoPlay
											loop={false}
											onAnimationFinish={() => {
												setIsFinished(true)
											}}
										/>
									) : (
										<LottieView
											source={require('./Berty_onboard_animation_assets2/Startup animation assets/Finish loop.json')}
											autoPlay
											loop
										/>
									)}
								</>
							)}
						</View>
						<View style={{ flex: 1 }}>
							<SwiperCard
								title={t('onboarding.setup-finished.title')}
								description={t('onboarding.setup-finished.desc')}
								button={{
									text: t('onboarding.setup-finished.button'),
									onPress: () => {
										Vibration.vibrate([500])
										navigation.dispatch(
											CommonActions.reset({
												routes: [{ name: Routes.Root.Tabs, params: { screen: Routes.Main.Home } }],
											}),
										)
									},
								}}
							/>
						</View>
					</>
				) : (
					<>
						<View style={{ flex: 1 }}>
							<LottieView
								source={require('./Berty_onboard_animation_assets2/Startup animation assets/Berty BG.json')}
								autoPlay
								loop
								style={{ width: '100%' }}
							/>
							{isGeneration === 1 && (
								<LottieView
									source={require('./Berty_onboard_animation_assets2/Startup animation assets/Code generation row 1.json')}
									autoPlay
									loop={false}
									speed={2}
									onAnimationFinish={() => {
										client ? setIsAccount(true) : setIsGeneration(2)
									}}
								/>
							)}
							{isGeneration === 2 && (
								<LottieView
									source={require('./Berty_onboard_animation_assets2/Startup animation assets/Code generation row 2.json')}
									autoPlay
									loop={false}
									speed={2}
									onAnimationFinish={() => {
										client ? setIsAccount(true) : setIsGeneration(3)
									}}
								/>
							)}
							{isGeneration === 3 && (
								<LottieView
									source={require('./Berty_onboard_animation_assets2/Startup animation assets/Code generation row 3.json')}
									autoPlay
									loop={false}
									speed={2}
									onAnimationFinish={() => {
										client ? setIsAccount(true) : setIsGeneration(4)
									}}
								/>
							)}
							{isGeneration === 4 && (
								<LottieView
									source={require('./Berty_onboard_animation_assets2/Startup animation assets/Code generation row 4.json')}
									autoPlay
									loop={false}
									speed={2}
									onAnimationFinish={() => {
										client ? setIsAccount(true) : setIsGeneration(1)
									}}
								/>
							)}
						</View>
						<View style={{ flex: 1 }}>
							<SwiperCard
								title={t('onboarding.generate-key.title')}
								description={t('onboarding.generate-key.desc')}
							>
								<Spinner size='large' />
							</SwiperCard>
						</View>
					</>
				)
			}
		</Translation>
	)
}

export const Performance: React.FC<{
	authorizeNotifications: Form<{}>
	authorizeBluetooth: Form<{}>
}> = ({ authorizeNotifications, authorizeBluetooth }) => {
	const { onLayout, height } = useLayout()
	const swiperRef = useRef<Swiper>(null)
	const next: (index: number) => () => void = (index) => (): void => {
		swiperRef && swiperRef.current && swiperRef.current.scrollTo(index, true)
	}
	const [{ absolute, background }] = useStyles()
	const [clickedCreate, setClickedCreate] = useState(false)
	return (
		<SafeAreaView style={[absolute.fill, background.blue]}>
			<View style={absolute.fill} onLayout={onLayout}>
				<KeyboardAvoidingView style={[absolute.fill]} behavior='padding'>
					<Swiper
						height={height}
						index={0}
						ref={swiperRef}
						activeDotStyle={[background.white]}
						scrollEnabled={false}
					>
						{!clickedCreate && (
							<CreateYourAccount next={next(2)} onCreate={() => setClickedCreate(true)} />
						)}
						{/*<SafeAreaView style={absolute.fill}>
							<Notifications submit={authorizeNotifications} next={next(4)} />
						</SafeAreaView>
						<Bluetooth submit={authorizeBluetooth} next={next(5)} />*/}
						{clickedCreate && <SetupFinished />}
					</Swiper>
				</KeyboardAvoidingView>
			</View>
		</SafeAreaView>
	)
}

export const Privacy: React.FC<{}> = () => {
	const { onLayout, ...layout } = useLayout()
	const swiperRef = useRef<Swiper>(null)
	const next: (index: number) => () => void = (index) => (): void => {
		swiperRef && swiperRef.current && swiperRef.current.scrollTo(index, true)
		return
	}
	const [{ absolute, background }] = useStyles()
	const [clickedCreate, setClickedCreate] = useState(false)
	return (
		<SafeAreaView style={[absolute.fill, background.red]} onLayout={onLayout}>
			<View style={absolute.fill} onLayout={onLayout}>
				<KeyboardAvoidingView style={[absolute.fill]} behavior='padding'>
					<Swiper
						height={layout.height}
						ref={swiperRef}
						activeDotStyle={[background.white]}
						scrollEnabled={false}
					>
						{!clickedCreate && (
							<CreateYourAccount next={next(2)} setClickedCreate={setClickedCreate} />
						)}
						{clickedCreate && <SetupFinished />}
					</Swiper>
				</KeyboardAvoidingView>
			</View>
		</SafeAreaView>
	)
}
