import React from 'react';
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
import { FlatList, StyleSheet, Text, View } from 'react-native';
import { connect } from 'react-redux';
import { RadioButton } from 'react-native-ui-lib';
import { RouteProp } from '@react-navigation/native';

import { ChatsStackParamList } from '../stacks/types';
import log from '../lib/methods/helpers/log';
import * as List from '../containers/List';
import I18n from '../i18n';
import * as HeaderButton from '../containers/HeaderButton';
import StatusBar from '../containers/StatusBar';
import { themes } from '../lib/constants';
import { TSupportedThemes, withTheme } from '../theme';
import SafeAreaView from '../containers/SafeAreaView';
import { animateNextTransition } from '../lib/methods/helpers/layoutAnimation';
import { ICON_SIZE } from '../containers/List/constants';
import SearchBox from '../containers/SearchBox';
import sharedStyles from './Styles';
import { IApplicationState } from '../definitions';
import { TDataSelect } from '../definitions/IDataSelect';

const styles = StyleSheet.create({
	buttonText: {
		fontSize: 16,
		margin: 16,
		...sharedStyles.textRegular
	}
});

interface ISelectListViewState {
	data?: TDataSelect[];
	dataFiltered?: TDataSelect[];
	isSearching: boolean;
	selected: string[];
}

interface ISelectListViewProps {
	navigation: StackNavigationProp<ChatsStackParamList, 'SelectListView'>;
	route: RouteProp<ChatsStackParamList, 'SelectListView'>;
	theme: TSupportedThemes;
	isMasterDetail: boolean;
}

class SelectListView extends React.Component<ISelectListViewProps, ISelectListViewState> {
	private title: string;

	private infoText: string;

	private nextAction: (selected: string[]) => void;

	private showAlert: () => void;

	private isSearch: boolean;

	private onSearch?: (text: string) => Promise<TDataSelect[] | any>;

	private isRadio?: boolean;

	constructor(props: ISelectListViewProps) {
		super(props);
		const data = props.route?.params?.data;
		this.title = props.route?.params?.title;
		this.auxiliaryText = props.route?.params?.auxiliaryText ?? '';
		this.nextAction = props.route?.params?.nextAction;
		this.showAlert = props.route?.params?.showAlert ?? (() => {});
		this.isSearch = props.route?.params?.isSearch ?? false;
		this.onSearch = props.route?.params?.onSearch;
		this.isRadio = props.route?.params?.isRadio;
		this.state = {
			data,
			dataFiltered: [],
			isSearching: false,
			selected: []
		};
		this.setHeader();
	}

	setHeader = () => {
		const { navigation, isMasterDetail } = this.props;
		const { selected } = this.state;

		const options: StackNavigationOptions = {
			headerTitle: I18n.t(this.title)
		};

		if (isMasterDetail) {
			options.headerLeft = () => <HeaderButton.CloseModal navigation={navigation} />;
		}

		options.headerRight = () => (
			<HeaderButton.Container>
				<HeaderButton.Item title={I18n.t('Next')} onPress={() => this.nextAction(selected)} testID='select-list-view-submit' />
			</HeaderButton.Container>
		);

		navigation.setOptions(options);
	};

	renderInfoText = () => {
		const { theme } = this.props;
		return (
			<View style={{ backgroundColor: themes[theme].backgroundColor }}>
				<Text style={[styles.buttonText, { color: themes[theme].bodyText }]}>{I18n.t(this.auxiliaryText)}</Text>
			</View>
		);
	};

	renderSearch = () => <SearchBox onChangeText={(text: string) => this.search(text)} testID='select-list-view-search' />;

	search = async (text: string) => {
		try {
			this.setState({ isSearching: true });
			const result = await this.onSearch?.(text);
			this.setState({ dataFiltered: result });
		} catch (e) {
			log(e);
		}
	};

	isChecked = (rid: string) => {
		const { selected } = this.state;
		return selected.includes(rid);
	};

	toggleItem = (rid: string) => {
		const { selected } = this.state;

		animateNextTransition();
		if (this.isRadio) {
			if (!this.isChecked(rid)) {
				this.setState({ selected: [rid] }, () => this.setHeader());
			}
		} else if (!this.isChecked(rid)) {
			this.setState({ selected: [...selected, rid] }, () => this.setHeader());
		} else {
			const filterSelected = selected.filter(el => el !== rid);
			this.setState({ selected: filterSelected }, () => this.setHeader());
		}
	};

	renderItem = ({ item }: { item: TDataSelect }) => {
		const { theme } = this.props;
		const { selected } = this.state;

		const channelIcon = item.t === 'p' ? 'channel-private' : 'channel-public';
		const teamIcon = item.t === 'p' ? 'teams-private' : 'teams';
		const icon = item.teamMain ? teamIcon : channelIcon;
		const checked = this.isChecked(item.rid) ? 'check' : '';

		const showRadio = () => (
			<RadioButton
				testID={selected ? `radio-button-selected-${item.name}` : `radio-button-unselected-${item.name}`}
				selected={selected.includes(item.rid)}
				color={themes[theme].tintColor}
				size={ICON_SIZE}
			/>
		);
		const showCheck = () =>
			checked !== '' ? (
				<List.Icon
					testID={checked ? `${item.name}-checked` : `${item.name}-unchecked`}
					name={checked}
					color={themes[theme].tintColor}
				/>
			) : null;

		return (
			<>
				<List.Separator />
				<List.Item
					title={item.name}
					translateTitle={false}
					testID={`select-list-view-item-${item.name}`}
					onPress={() => (item.alert ? this.showAlert() : this.toggleItem(item.rid))}
					alert={item.alert}
					left={() => <List.Icon name={icon} color={themes[theme].auxiliaryText} />}
					right={() => (this.isRadio ? showRadio() : showCheck())}
				/>
			</>
		);
	};

	render() {
		const { data, isSearching, dataFiltered } = this.state;
		const { theme } = this.props;
		return (
			<SafeAreaView testID='select-list-view'>
				<StatusBar />
				<FlatList
					data={!isSearching ? data : dataFiltered}
					extraData={this.state}
					keyExtractor={item => item.rid}
					renderItem={this.renderItem}
					ListHeaderComponent={this.isSearch ? this.renderSearch : this.renderInfoText}
					contentContainerStyle={{ backgroundColor: themes[theme].backgroundColor }}
					keyboardShouldPersistTaps='always'
				/>
			</SafeAreaView>
		);
	}
}

const mapStateToProps = (state: IApplicationState) => ({
	isMasterDetail: state.app.isMasterDetail
});

export default connect(mapStateToProps)(withTheme(SelectListView));
