import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { State, LongPressGestureHandler } from 'react-native-gesture-handler';
import {
	StyleSheet,
	View,
	Dimensions,
	TouchableOpacity,
	LayoutAnimation,
	UIManager,
	Platform,
} from 'react-native';
import DeviceInfo from 'react-native-device-info';
import Animated from 'react-native-reanimated';
import {
	Image,
	NixplayIcon,
	Text,
	color,
	transparentize,
} from 'nixplay-ui-kit';

import moment from 'moment';
import _ from 'lodash';
import FastImage from 'react-native-fast-image';

import * as TEST_IDS from '~/store/testIDConstants';
import setTestID from '~/test/testUtils';

const Screen = {
	height: Dimensions.get('window').height,
	width: Dimensions.get('window').width,
};
const thumbHeight = (Screen.width / 3) - 2;

const styles = StyleSheet.create({
	thumb: {
		flex: 1,
	},
	dot: {
		backgroundColor: color.red,
		width: 10,
		height: 10,
		borderRadius: 5,
		position: 'absolute',
		right: 4,
		top: 4,
	},
	marginCorrection: {
		right: 10,
	},
	placeholder: {
		width: thumbHeight,
		height: thumbHeight,
		margin: 1,
		backgroundColor: color.mistBlue03,
	},
	videoIconContainer: {
		position: 'absolute',
		bottom: 4,
		left: 4,
		backgroundColor: transparentize(color.white, 20),
		paddingHorizontal: 8,
		paddingVertical: 2,
		borderRadius: 8,
		flexDirection: 'row',
		alignItems: 'center',
	},
	videoDuration: {
		marginLeft: 4,
	},
	selectedIcon: {
		position: 'absolute',
		top: 4,
		right: 4,
		width: 24,
		height: 24,
		borderRadius: 12,
		backgroundColor: color.white,
		shadowOffset: { width: 0, height: 1 },
		shadowColor: color.black,
		shadowOpacity: 0.2,
		shadowRadius: 2,
		elevation: 1,
	},
});

const videoDuration = (seconds) => {
	const duration = moment.duration(seconds, 'seconds');
	return `${_.padStart(duration.minutes(), 2, 0)}:${_.padStart(duration.seconds(), 2, 0)}`;
};

const hasNotch = DeviceInfo.hasNotch();
const isIOS = Platform.OS === 'ios';
const HEADER_PADDING = hasNotch ? 38 : 70;
const {
	cond,
	eq,
	sub,
	Value,
	event,
	call,
} = Animated;

if (Platform.OS === 'android') {
	if (UIManager.setLayoutAnimationEnabledExperimental) {
		UIManager.setLayoutAnimationEnabledExperimental(true);
	}
}

class Thumbnail extends Component {
	constructor(props) {
		super(props);
		this.state = {
			dragging: false,
			currentIndex: -1,
		};
		this.dragging = new Value(0);
		this.X = new Value(0);
		this.Y = new Value(0);
		this.minIndex = -1;
		this.activeIndex = new Value(0);
		this.gestureState = new Value(-1);
		this.scrolling = false;
		this.selectedIndex = -1;
		this.offsetX = new Value(0);
		this.offsetY = new Value(0);
		this.holderX = 0;
		this.holderY = 0;
		this.floating = false;
		this.holderIndex = -1;
		this.scale = new Value(0.8);
		this.floatingScale = new Value(0.8);
		this.onGestureEvent = event([
			{
				nativeEvent: {
					absoluteX: this.X,
					absoluteY: this.Y,
					state: this.gestureState,
				},
			},
		], { useNativeDriver: true });
	}

	shouldComponentUpdate(nextProps, nextState) {
		if (!_.isEqual(nextProps.selectedContent, this.props.selectedContent) ||
			!_.isEqual(nextProps.dragMode, this.props.dragMode) ||
			!_.isEqual(nextProps.selectMode, this.props.selectMode) ||
			!_.isEqual(nextProps.activeIndex, this.props.activeIndex) ||
			!_.isEqual(nextProps.index, this.props.index) ||
			!_.isEqual(nextState.dragging, this.state.dragging)) {
			return true;
		}
		return false;
	}

	getActiveIndex = async ([Y, X]) => {
		const {
			setActiveIndex, scrollY, index,
		} = this.props;

		this.selectedIndex = index;

		if (Y > Screen.height - 100) {
			this.props.setDraggingTrue();
			this.props.scrollList(5);
		} else if (Y < 100) {
			this.props.setDraggingTrue();
			this.props.scrollList(-5);
		} else {
			this.props.setDraggingFalse();
			const holderX = Math.floor(X / (thumbHeight + 2));
			const holderY = (Y + HEADER_PADDING + scrollY) / (thumbHeight + 2);
			const indexHolder = ((Math.floor(holderY) * 3) - 3) + holderX;

			this.setState({ currentIndex: indexHolder });
			setActiveIndex(indexHolder);
			LayoutAnimation.configureNext(LayoutAnimation.create(100, 'easeOut', 'opacity'));
		}

		this.setState({ dragging: true });

		// this.selectedIndex = index;
		// const holderX = Math.floor(X / (thumbHeight + 2));
		// const holderY = (Y + HEADER_PADDING + scrollY) / (thumbHeight + 2);
		// const indexHolder = ((Math.floor(holderY) * 3) - 3) + holderX;

		// setActiveIndex(indexHolder);
		// this.setState({ currentIndex: indexHolder, activeIndex: index });
		// this.thumbref.measure( (fx, fy, width, height, px, py) => {

		// 	console.log('Component width is: ' + width)
		// 	console.log('Component height is: ' + height)
		// 	console.log('X offset to frame: ' + fx)
		// 	console.log('Y offset to frame: ' + fy)
		// 	console.log('X offset to page: ' + px)
		// 	console.log('Y offset to page: ' + py)
		// 	console.log(scrollY)
		// })
		// console.log(indexHolder);

		// block([
		// 	set(this.holderX, floor(divide(X, thumbHeight))),
		// 	set(this.holderY, floor(divide(add(Y, HEADER_PADDING), add(thumbHeight, 2)))),
		// 	set(this.holderIndex, add(this.holderX, multiply(sub(this.holderY, 1), 3))),
		// ])
	}

	setFloatingComponent = () => {
		if (!this.floating) {
			this.floating = true;
			this.props.setFloatingComponent(this.renderFloatingComponent);
		}
	}

	// setFloatingComponent = () => {
	// 	const Component = '<View><Text>HELLO</Text><View/>';
	// 	this.props.floatingComponent(Component);
	// }

	// scrollList = (index) => {
	// 	const { scrollY } = this.props;
	// 	this.props.getFlatListRef().getNode().scrollToIndex({
	// 		offset: index,
	// 		animated: false,
	// 	});
	// }

	reset = async () => {
		const { onMoveEnd, activeIndex } = this.props;
		const { currentIndex } = this.state;
		this.props.setDraggingFalse();
		this.setState({ dragging: false });
		this.floating = false;
		if (this.minIndex === -1 || this.minIndex < this.selectedIndex) {
			this.minIndex = this.selectedIndex;
		}
		if (!_.isEqual(this.selectedIndex, activeIndex)) {
			if (this.selectedIndex < currentIndex) { // from upper slot to lower slot
				onMoveEnd(this.selectedIndex, currentIndex + 1);
			} else { // from lower slot to upper slot
				onMoveEnd(this.selectedIndex, currentIndex);
			}
		}
		this.props.setActiveIndex(-1);
	}

	renderFloatingComponent = () => {
		const { photo } = this.props;
		const { dragging } = this.state;
		const photoUrl = (!_.isEmpty(photo.microThumbnailUrl) && photo.microThumbnailUrl.indexOf('MICRO_THUMBNAIL') >= 1) ? photo.microThumbnailUrl : photo.thumbnailUrl;

		return dragging && (
			<Animated.View style={{
				position: 'absolute',
				top: sub(this.Y, thumbHeight / 2),
				left: sub(this.X, thumbHeight / 2),
				width: thumbHeight,
				height: thumbHeight,
				backgroundColor: 'green',
				transform: [
					{ scale: this.floatingScale },
				],
				shadowColor: '#000',
				shadowOffset: {
					width: 0,
					height: 5,
				},
				shadowOpacity: 0.34,
				shadowRadius: 6.27,

				elevation: 10,
			}}
			>
				<Image
					source={{
						uri: photo.thumbnailUrl.includes('dropbox') ? decodeURIComponent(photo.thumbnailUrl) : photoUrl,
						priority: FastImage.priority.low,
					}}
					style={{ width: thumbHeight, height: thumbHeight }}
					initImageStyle={{ backgroundColor: color.mistBlue03, flex: 1 }}
					transform={[{
						rotate: `${(_.isNil(photo.rotation) ? 0 : photo.rotation)}deg`,
					}]}
					resizeMode="cover"
					withProgress
					useShimmer
					indicatorProps={{
						backgroundColor: color.mistBlue03,
						height: thumbHeight,
						width: thumbHeight,
						margin: 1,
						justifyContent: 'center',
						alignItems: 'center',
					}}
					isIndicatorNative
				/>
			</Animated.View>
		);
	}

	render() {
		const {
			photo, dragMode, activeIndex, index, onPressContent, playlistLastSeenTimestamp,
			isSharedPlaylist, onLongPressContent, selectMode, playlistId,
			// itemSelectable
		} = this.props;
		const photoUrl = (!_.isEmpty(photo.microThumbnailUrl) && photo.microThumbnailUrl.indexOf('MICRO_THUMBNAIL') >= 1) ? photo.microThumbnailUrl : photo.thumbnailUrl;
		const { dragging } = this.state;
		// const isShared = this.props.isSharedPlaylist;
		// const isPlaylistOwned = this.props.isOwner;
		// const isMatchUser = (selectMode && _.isEqual(photo.username, this.props.username));
		// const thumbOpacity = (isPlaylistOwned || isMatchUser) ? 1 : 0.5;


		// const disabled = itemSelectable !== -1 ? !itemSelectable(this.props.photo) : false;
		// const opacity = (selectMode && isShared) ? thumbOpacity : 1.0;
		// const photoPrintOpacity = disabled ? 0.5 : 1.0;

		const photoTimestamp = (photo.timestamp === undefined) ? playlistLastSeenTimestamp : photo.timestamp;
		const isRedDot = (parseInt(photoTimestamp, 0) >= parseInt(playlistLastSeenTimestamp, 0));

		return (
			// <PanGestureHandler
			// 	// maxPointers={1}
			// 	// maxDeltaY={20}
			// 	// maxDeltaX={20}
			// 	minDist={23}
			// 	ref={(ref) => { this.panGestureRef = ref; }}
			// 	simultaneousHandlers={this.longPressRef}
			// 	waitFor={this.props.getFlatListRef()}
			// 	onHandlerStateChange={this.onGestureEvent}
			// 	onGestureEvent={this.onGestureEvent}
			// >
			// 	<TouchableOpacity
			// 		activeOpacity={0.8}
			// 		style={styles.placeholder}
			// 		// onLongPress={(e) => onLongPressContent(photo.id, index, e, moveStart)}
			// 		onPress={() => onPressContent(photo.id, index)}
			// 		{...setTestID(`${TEST_IDS.THUMBNAIL}${index}`)}
			// 	>
			// 	<Animated.View style={{margin: 1}}>
			// <TapGestureHandler
			// 	onHandlerStateChange={(e) => {
			// 		if (e.nativeEvent.state === State.ACTIVE) {
			// 			onPressContent(photo.id, index);
			// 		}
			// 	}}
			// >
			// 	<Animated.View>
			<LongPressGestureHandler
				onHandlerStateChange={this.onGestureEvent}
				onGestureEvent={this.onGestureEvent}
				minDurationMs={150}
				enabled={dragMode}
				numberOfPointers={1}
				// Hotfix for gestureHandler on Android
				{...(!isIOS && { maxDist: 999999 })}
				shouldCancelWhenOutside={false}
				ref={(ref) => { this.longPressRef = ref; }}
				{...setTestID(`${TEST_IDS.THUMBNAIL}${index}`)}
			>
				<Animated.View
					style={{
						width: thumbHeight,
						height: thumbHeight,
						margin: 1,
					}}
				>
					<TouchableOpacity
						{...setTestID(`${TEST_IDS.THUMBNAIL}${index}`)}
						activeOpacity={0.8}
						enabled={!dragMode}
						style={{ flexDirection: 'row' }}
						onPress={() => onPressContent(photo.id, index, playlistId)}
						onLongPress={() => onLongPressContent(photo.id, index)}
					>

						<Animated.Code>
							{() => cond(eq(this.gestureState, State.ACTIVE), [
								call([this.Y, this.X], this.getActiveIndex),
								call([], this.setFloatingComponent),
							])
							}
						</Animated.Code>
						<Animated.Code>
							{() => cond(eq(this.gestureState, State.END), [
								call([], this.setFloatingComponent),
								call([this.Y], this.reset),
								call([], () => { this.floating = false; }),
							])
							}
						</Animated.Code>
						<Animated.View style={{
							width: _.isEqual(activeIndex, index) ? 3 : 0,
							backgroundColor: color.blue,
							height: thumbHeight,
							top: 0,
							left: 0,
						}}
						/>
						<Animated.View
							style={{
								flex: 1,
								transform: [{ scale: dragMode ? this.scale : 1 }],
								// transform: [{ scale: 1 }],
								backgroundColor: color.mistBlue03,
							}}
						>
							{!dragging && <Image
								source={{
									uri: photo.thumbnailUrl.includes('dropbox') ? decodeURIComponent(photo.thumbnailUrl) : photoUrl,
									priority: FastImage.priority.low,
								}}
								// style={[styles.thumb, {
								// 	opacity: (this.props.selectMode) ? thumbOpacity : 1.0,
								// }]}
								style={styles.thumb}
								initImageStyle={{ backgroundColor: color.mistBlue03, flex: 1 }}
								transform={[{
									rotate: `${(_.isNil(photo.rotation) ? 0 : photo.rotation)}deg`,
								}]}
								resizeMode="cover"
								withProgress
								indicatorProps={{
									backgroundColor: color.mistBlue03,
									height: thumbHeight,
									width: thumbHeight,
									margin: 1,
									justifyContent: 'center',
									alignItems: 'center',
								}}
								useShimmer
								isIndicatorNative
							/>}
						</Animated.View>
						{!_.isEmpty(photo.videoUrl) &&
						<View style={styles.videoIconContainer}>
							<NixplayIcon
								name="video-solid"
								color="textGrey"
								size={12}
							/>
							<Text
								textStyle="caption2"
								color="textGrey"
								style={styles.videoDuration}
							>
								{videoDuration(photo.videoDuration)}
							</Text>
						</View>
						}
						{this.props.selectMode && this.props.selectedContent.indexOf(photo.id) >= 0 &&
						<View style={styles.selectedIcon}>
							<NixplayIcon
								name="checkbox-circle-on"
								color="blue"
							/>
						</View>
						}
						{(isRedDot && isSharedPlaylist && !selectMode && !dragMode) && <View style={[styles.dot]} /> }
						{<Animated.View style={{
							width: _.isEqual(activeIndex - 1, index) ? 3 : 0,
							height: thumbHeight,
							top: 0,
							left: 0,
						}}
						/>}
					</TouchableOpacity>
				</Animated.View>
			</LongPressGestureHandler>
			// 	</Animated.View>
			// </TapGestureHandler>
		);
	}
}

Thumbnail.propTypes = {
	photo: PropTypes.object,
	index: PropTypes.number,
	onPressContent: PropTypes.func,
	onLongPressContent: PropTypes.func,
	selectMode: PropTypes.bool,
	selectedContent: PropTypes.array,
	moveStart: PropTypes.func,
	username: PropTypes.string,
	playlistLastSeenTimestamp: PropTypes.number,
	isSharedPlaylist: PropTypes.bool,
	isOwner: PropTypes.bool,
	itemSelectable: PropTypes.any,
	setActiveIndex: PropTypes.func,
	scrollY: PropTypes.number,
	dragMode: PropTypes.bool,
	activeIndex: PropTypes.number,
	onMoveEnd: PropTypes.func,
	setDraggingFalse: PropTypes.func,
	setDraggingTrue: PropTypes.func,
	setFloatingComponent: PropTypes.func,
	scrollList: PropTypes.func,
	playlistId: PropTypes.number,
};

Thumbnail.defaultProps = {
	photo: { thumbnailUrl: '' },
	scrollY: 0,
	playlistId: 0,
	setFloatingComponent: () => {},
	scrollList: () => {},
	playlistLastSeenTimestamp: -1,
	index: 0,
	onPressContent: () => {},
	onLongPressContent: () => {},
	setActiveIndex: () => {},
	selectMode: false,
	selectedContent: [],
	moveStart: () => {},
	onMoveEnd: () => {},
	username: '',
	isSharedPlaylist: false,
	isOwner: false,
	itemSelectable: -1,
	setDraggingFalse: () => {},
	setDraggingTrue: () => {},
	dragMode: false,
	activeIndex: -1,
};

export default Thumbnail;
