import React, { Component } from 'react';
import {
	View,
	Dimensions,
	TouchableOpacity,
	StyleSheet,
	ActivityIndicator,
	Platform,
} from 'react-native';
import { SafeAreaView } from 'react-navigation';
import Video from 'react-native-video';
import { Image, color, Text } from 'nixplay-ui-kit';
import PropTypes from 'prop-types';
import { ifIphoneX } from 'react-native-iphone-x-helper';
import FastImage from 'react-native-fast-image';
import _ from 'lodash';

import {
	VIDEO_STATE_IDLE,
	VIDEO_STATE_LOADING,
	VIDEO_STATE_LOADED,
	VIDEO_STATE_PLAYING,
} from '~/store/contentTypes';
import playButton from '~/images/general/play-button.png';
import { Avatar } from '~comp/SharedPlaylist/avatar';

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

const styles = StyleSheet.create({
	container: {
		flex: 1,
		justifyContent: 'center',
		alignItems: 'center',
	},
	videoContainer: {
		flex: 1,
		width: '100%',
		height: '100%',
	},
	video: {
		flex: 1,
	},
	image: {
		width: '100%',
		height: '100%',
	},
	playButtonContainer: {
		position: 'absolute',
		left: (width / 2) - 50,
		top: (height / 2) - 50,
		bottom: 0,
		right: 0,
		width: 100,
		height: 100,
		justifyContent: 'center',
		alignItems: 'center',
		padding: 8,
	},
	playButton: {
		flex: 1,
		width: 52,
		height: 52,
	},

	loadingContainer: {
		position: 'absolute',
		left: (width / 2) - 25,
		top: (height / 2) - 25,
		bottom: 0,
		right: 0,
		width: 50,
		height: 50,
		justifyContent: 'center',
		alignItems: 'center',
	},
	loading: {
		flex: 1,
	},
});

const isIOS = Platform.OS === 'ios';
const isAndroid = Platform.OS === 'android';

export class ContentPreview extends Component {
	static propTypes = {
		item: PropTypes.any,
		onVideoPlay: PropTypes.func,
		onVideoPause: PropTypes.func,
		onVideoError: PropTypes.func,
		userId: PropTypes.number,
	}

	static defaultProps = {
		item: {},
		userId: 0,
		onVideoPlay: () => { },
		onVideoPause: () => { },
		onVideoError: () => { },
	}

	constructor(props) {
		super(props);

		this.state = {
			paused: true,
			imgWidth: 0,
			imgHeight: 0,
			isMounted: false,
			currentTime: 0,
			showLoadingIndicator: false,
			showCustomAndroidLoadingIndicator: false,
			videoStatus: VIDEO_STATE_IDLE,
			showPreview: true,
		};

		this.pauseVideo = this.pauseVideo.bind(this);
		this.onLoad = this.onLoad.bind(this);
		this.onEnd = this.onEnd.bind(this);
	}

	shouldComponentUpdate(nextProps, nextState) {
		if (!_.isEqual(nextState.paused, this.state.paused) ||
			!_.isEqual(nextState.showLoadingIndicator, this.state.showLoadingIndicator) ||
			!_.isEqual(nextState.showCustomAndroidLoadingIndicator, this.state.showCustomAndroidLoadingIndicator) ||
			!_.isEqual(nextState.showPreview, this.state.showPreview) ||
			!_.isEqual(nextState.videoStatus, this.state.videoStatus) ||
			!_.isEqual(nextProps.item.previewUrl, this.props.item.previewUrl) ||
			!_.isEqual(nextProps.item.userAvatar, this.props.item.userAvatar) ||
			// !_.isEqual(nextProps.item.userFullName, this.props.item.userFullName) || // it keeps re-rendering
			!_.isEqual(nextProps.userId, this.props.userId)) {
			return true;
		}
		return false;
	}

	componentDidUpdate(prevProps) {
		if (this.isVideo()) {
			if (!_.isEqual(prevProps, this.props)) {
				// eslint-disable-next-line react/no-did-update-set-state
				this.setState({ paused: true }, () => {
					if (this.player !== undefined) {
						this.player.seek(0);
					}
				});
			}
		}
	}

	componentWillUnmount() {
		this.setState({ isMounted: false });
	}

	onEnd = () => {
		this.setState({ paused: true, currentTime: 0 }, () => {
			if (this.player !== undefined) {
				this.player.seek(0);
			}
		});
	}

	onLoadStart = () => {
		this.setState({ showLoadingIndicator: true, videoStatus: VIDEO_STATE_LOADING });
	}

	onLoad = () => {
		this.player.seek(0);
		this.setState({
			showLoadingIndicator: true,
			showPreview: true,
			currentTime: 0,
			videoStatus: VIDEO_STATE_LOADED,
		});
	}

	onProgress = ({ currentTime }) => {
		this.setState((prevState) => {
			const loading = _.isEqual(prevState.videoStatus, VIDEO_STATE_LOADING);
			const showLoadingIndicator = (loading || _.isEqual(Math.abs(prevState.currentTime - currentTime), 0));
			const showPreview = (loading || _.isEqual(currentTime, 0));
			return {
				currentTime,
				showLoadingIndicator,
				showPreview,
				videoStatus: VIDEO_STATE_PLAYING,
			};
		});
	}

	playVideo = () => {
		this.setState({ isMounted: true, showLoadingIndicator: true }, () => {
			if (this.isVideo()) {
				this.setState({ paused: !this.state.paused }, () => {
					this.props.onVideoPlay(this.pauseVideo);
				});
				if (this.player !== undefined) {
					if (_.isEqual(this.state.currentTime, 0)) {
						this.player.seek(this.state.currentTime);
					}
				}
			}
		});
	}

	pauseVideo = () => {
		if (this.isVideo()) {
			this.setState({ paused: true, showLoadingIndicator: false }, () => {
				this.props.onVideoPause();
			});
		}
	}

	isVideo = () => (!_.isEmpty(this.props.item.videoUrl));

	render() {
		const { imgWidth, imgHeight } = this.state;
		const { item } = this.props;
		const userAvatar = (!_.isEmpty(item.userAvatar)) ? { uri: item.userAvatar.avatar.url } : null;
		// alter object due to different avatar component source
		if (_.has(userAvatar, 'cache')) {
			userAvatar.cache = 'reload';
		}
		const isShared = !_.isEmpty(item.userFullName);
		const isVideo = !_.isEmpty(item.videoUrl);
		const name = !_.isEmpty(item.userFullName) ? item.userFullName.split(' ') : '';
		return (
			<SafeAreaView style={styles.container} key={this.props.item.id}>
				{isVideo &&
					<TouchableOpacity
						activeOpacity={this.state.paused ? 1.0 : 0.8}
						style={styles.videoContainer}
						onPressIn={(!this.state.paused) ? this.pauseVideo : () => {}}
					>
						{this.state.isMounted && <Video
							ref={(ref) => {
								this.player = ref;
							}}
							bufferConfig={{
								minBufferMs: 5000,
								maxBufferMs: 15000,
								bufferForPlaybackMs: 2000,
								bufferForPlaybackAfterRebufferMs: 5000,
							}}
							paused={this.state.paused}
							source={{ uri: this.props.item.videoUrl, isAssets: false }}
							onLoad={this.onLoad}
							onEnd={this.onEnd}
							onError={this.props.onVideoError}
							onProgress={this.onProgress}
							onLoadStart={this.onLoadStart}
							style={styles.video}
							resizeMode="contain"
							useTextureView
						/>}
					</TouchableOpacity>}
				{ isIOS ? ((this.state.showPreview || this.state.paused) && <Image
					source={{
						uri: this.props.item.previewUrl,
						cache: FastImage.cacheControl.web,
						priority: FastImage.priority.high,
					}}
					style={{
						width: imgWidth,
						height: imgHeight,
						position: 'relative',
					}}
					transform={[{
						rotate: `${this.props.item.rotation}deg`,
					}]}
					onLoadStart={() => {
						if (this.props.item.rotation % 180 === 0) {
							this.setState({ imgWidth: width, imgHeight: height, showLoadingIndicator: true });
						} else {
							this.setState({ imgWidth: height, imgHeight: width, showLoadingIndicator: true });
						}
					}}
					onLoadEnd={() => { this.setState({ showLoadingIndicator: false }); }}
					resizeMode="contain"
					withProgress={!isVideo}
				/>) : (
					<View pointerEvents={(this.state.showPreview || this.state.paused) ? 'auto' : 'none'} style={{ position: 'absolute' }}>
						<Image
							source={{
								uri: this.props.item.previewUrl,
								cache: FastImage.cacheControl.web,
								priority: FastImage.priority.high,
							}}
							style={{
								width: imgWidth,
								height: imgHeight,
								opacity: (this.state.showPreview ? 1 : 0),
							}}
							transform={[{
								rotate: `${this.props.item.rotation}deg`,
							}]}
							onLoadStart={() => {
								if (this.props.item.rotation % 180 === 0) {
									this.setState({ imgWidth: width, imgHeight: height, showCustomAndroidLoadingIndicator: true });
								} else {
									this.setState({ imgWidth: height, imgHeight: width, showCustomAndroidLoadingIndicator: true });
								}
							}}
							onLoadEnd={() => { this.setState({ showCustomAndroidLoadingIndicator: false }); }}
							resizeMode="contain"
						/>
					</View>
				)}
				{isAndroid && !isVideo && this.state.showCustomAndroidLoadingIndicator &&
					<View
						style={styles.playButtonContainer}
					>
						<ActivityIndicator size="large" color={color.blue} />
					</View>
				}
				{isVideo && this.state.paused &&
					<TouchableOpacity
						style={styles.playButtonContainer}
						onPressIn={this.playVideo}
					>
						<Image
							source={playButton}
							style={styles.playButton}
							androidScaleType="center"
							resizeMode="contain"
						/>
					</TouchableOpacity>}
				{isVideo && (this.state.showLoadingIndicator && !this.state.paused) &&
					<TouchableOpacity
						style={styles.loadingContainer}
						onPressIn={this.playVideo}
					>
						<ActivityIndicator size="large" color={color.blue} />
					</TouchableOpacity>}
				{(isShared && !_.isEqual(this.props.userId, item.userProfileId)) &&
				<View style={{
					position: 'absolute',
					...ifIphoneX({
						top: 48,
					}, {
						top: 24,
					}),
					flexDirection: 'row',
					alignItems: 'center',
					justifyContent: 'center',
					alignSelf: 'center',
					maxWidth: '80%',
				}}
				>
					<View style={{
						position: 'absolute',
						backgroundColor: 'black',
						opacity: 0.5,
						height: '100%',
						width: '100%',
						borderRadius: 30,
					}}
					/>
					<Avatar firstName={`${name[0]}`} lastName={`${name[name.length - 1]}`} source={userAvatar} />
					<Text
						style={{
							paddingLeft: 10, paddingRight: 10, fontSize: 16,
						}}
						textStyle="title4"
						color="white"
						ellipsizeMode="tail"
						numberOfLines={1}
					>{item.userFullName}
					</Text>
				</View>}
			</SafeAreaView>
		);
	}
}
