/**
 * @providesModule ViewPager
 * @flow
 */

import React, { Component } from 'react';
import {
	View,
	ScrollView,
	StyleSheet,
	Platform,
	// Dimensions,
	// Element,
} from 'react-native';
import ViewPagerAndroid from '@react-native-community/viewpager';
import PropTypes from 'prop-types';

// const { width } = Dimensions.get('window');


const styles = StyleSheet.create({
	container: {
		flex: 1,
	},
});

class ViewPager extends Component {
	static propTypes = {
		onChangeThrottle: PropTypes.number,
		renderHeader: PropTypes.func,
		renderFooter: PropTypes.func,
		initialPage: PropTypes.number,
		onChangePage: PropTypes.func,
		children: PropTypes.array.isRequired,
		style: PropTypes.object,
	}

	static defaultProps = {
		onChangeThrottle: 250,
		renderHeader: null,
		renderFooter: null,
		initialPage: 0,
		onChangePage: () => {},
		style: {},
	}

	constructor(props) {
		super(props);
		this.state = {
			width: '100%',
		};

		this.active = 0;
		this.header = null;
		this.footer = null;
		this.pageDelayTimeout = null;
		this.viewPager = null;
		this.scrollView = null;

		// iOS only
		this.state = {
			width: 0,
			height: 0,
		};
	}

	// state: State;

	/**
	 * Call inital page handlers on mount
	 */
	componentDidMount() {
		if (this.header && this.header.onChangePage) {
			this.header.onChangePage(this.props.initialPage);
		}
		if (this.footer && this.footer.onChangePage) {
			this.footer.onChangePage(this.props.initialPage);
		}
	}

	/**
	 * Helper to set component refs
	 * @param type
	 * @param component
	 */
	// setRef = (type: string, component: any) => {
	// 	if (!component) {
	// 		this[type] = null;
	// 	} else {
	// 		this[type] = component;
	// 	}
	// }

	// /**
	//  * @param component
	//  */
	// setHeaderRef = (component: any) => {
	// 	this.setRef('header', component);
	// }

	// /**
	//  * @param component
	//  */
	// setFooterRef = (component: any) => {
	// 	this.setRef('footer', component);
	// };

	// props: Props;

	// viewPager: any;

	// scrollView: any;

	// active: number;

	// header: any;

	// footer: any;

	// pageDelayTimeout: ?setTimeout;

	/**
	 * Set the page dimensions
	 * @param e
	 */
	setDimensions = (e) => {
		this.setState({
			width: e.nativeEvent.layout.width,
			height: e.nativeEvent.layout.height,
		});
	}

	/**
	 * Gets the current page index
	 * @returns {number}
	 */
	currentPage = () => this.active;
	/**
	 * Handle a page change event
	 * @param e
	 * @returns {*}
	 */
	handlePageChange = (e) => {
		// Use ViewPager position
		if (Platform.OS === 'android') {
			return this.goToPage(e.nativeEvent.position);
		}

		// Calculate current index
		const index = e.nativeEvent.contentOffset.x / this.state.width;

		// Only call the function if the index is an integer (page)
		if (index === parseInt(index, 0)) {
			// Don't do anything if it's bouncing out of view
			if (index < 0 || index >= React.Children.count(this.props.children)) {
				return undefined;
			}

			return this.goToPage(index);
		}

		return undefined;
	}
	/**
	 * Manually navigate to a page
	 * @param page
	 */
	goToPage = (page, animated) => {
		this.active = page;

		if (Platform.OS === 'android') {
			if (animated) {
				this.viewPager.setPage(this.active);
			} else {
				this.viewPager.setPageWithoutAnimation(this.active);
			}
		} else {
			this.scrollView.scrollTo({
				x: this.active * this.state.width,
				animated,
			});
		}

		// Throttle page events to avoid spamming
		clearTimeout(this.pageDelayTimeout);
		this.pageDelayTimeout = setTimeout(() => {
			if (this.header && this.header.onChangePage) {
				this.header.onChangePage(this.active);
			}
			if (this.footer && this.footer.onChangePage) {
				this.footer.onChangePage(this.active);
			}
			if (this.props.onChangePage) this.props.onChangePage(this.active);
		}, this.props.onChangeThrottle || 250);
	}

	/**
	 * Render each child view in the ViewPager
	 * @returns {*}
	 */
	renderChildren = () => {
		const iosStyles = {};

		if (Platform.OS === 'ios') {
			iosStyles.width = this.state.width;
			iosStyles.height = this.state.height;
		}

		return React.Children.map(this.props.children, (child, index) => (
			// eslint-disable-next-line react/no-array-index-key
			<View key={`vp_${index}`} style={[styles.container, iosStyles]}>
				{child}
			</View>
		));
	}

	/**
	 * Render a paging ScrollView. No ViewPager exists on iOS.
	 * @returns {XML}
	 */
	renderIOS() {
		return (
			<ScrollView
				ref={(s) => { this.scrollView = s; }}
				horizontal
				pagingEnabled
				removeClippedSubviews
				directionalLockEnabled
				scrollEventThrottle={100}
				bounces={false}
				scrollsToTop={false}
				automaticallyAdjustContentInsets={false}
				showsHorizontalScrollIndicator={false}
				showsVerticalScrollIndicator={false}
				onScroll={(e) => this.handlePageChange(e)}
				onLayout={e => this.setDimensions(e)}
				contentOffset={{
					x: this.state.width * this.props.initialPage,
					y: 0,
				}}
			>
				{this.renderChildren()}
			</ScrollView>
		);
	}

	/**
	 * Render a native scrollView
	 * @returns {XML}
	 */
	renderAndroid() {
		return (
			<ViewPagerAndroid
				keyboardDismissMode="on-drag"
				ref={(v) => { this.viewPager = v; }}
				initialPage={this.props.initialPage}
				onPageSelected={e => this.handlePageChange(e)}
				style={styles.container}
			>
				{this.renderChildren()}
			</ViewPagerAndroid>
		);
	}

	/**
	 * Render
	 * @returns {XML}
	 */
	render() {
		const props = {
			initialPage: this.props.initialPage,
			goToPage: this.goToPage.bind(this),
			setHeaderRef: this.setHeaderRef,
			setFooterRef: this.setFooterRef,
		};

		let header = null;
		let footer = null;

		if (this.props.renderHeader) {
			header = React.cloneElement(this.props.renderHeader(props), props);
		}
		if (this.props.renderFooter) {
			footer = React.cloneElement(this.props.renderFooter(props), props);
		}

		return (
			<View style={[styles.container, this.props.style]}>
				{header}
				{Platform.OS === 'ios' ? this.renderIOS() : this.renderAndroid()}
				{footer}
			</View>
		);
	}
}


export default ViewPager;
