import React, { Component } from "react";
import { View, Animated, PanResponder, Image, StyleSheet } from "react-native";
import { Icon } from "@rneui/themed";
import { BOXGREY, TEXT_LIGHT } from "../colours";

class PositionedImage extends Component {
	constructor(props) {
		super(props);

		this.lastPos = { x: 0, y: 0 };
		this.imagePosition = new Animated.ValueXY(this.lastPos);
		this.imagePosition.addListener((value) => {
			this.lastPos = value;
		});
		const imagePanResponder = PanResponder.create({
			onStartShouldSetPanResponder: () => {
				this.startPos = this.lastPos;
				if (this.props.onPositionEnd) {
					if (this.props.onPositionStart) this.props.onPositionStart();
					this.setState({ panning: true });
					return true;
				}
				return false;
			},
			onPanResponderMove: (event, gesture) => {
				const newPos = this.state.isVertical
					? { x: 0, y: this.startPos.y + gesture.dy }
					: { x: this.startPos.x + gesture.dx, y: 0 };
				this.imagePosition.setValue(newPos);
			},
			onPanResponderTerminationRequest: (event, gesture) => true,
			onPanResponderRelease: (event, gesture) => {
				let endPos = { x: 0, y: 0 };
				if (this.state.isVertical) {
					const endY = this.startPos.y + gesture.dy;
					const limitY = this.props.height - this.state.imageHeight;
					if (endY > 0) {
						// console.log('top reached', endY);
						endPos = { x: 0, y: 0 };
					} else if (endY < limitY) {
						// console.log('bottom reached', endY, limitY);
						endPos = { x: 0, y: limitY };
					} else {
						endPos = { x: 0, y: endY };
					}
				} else {
					const endX = this.startPos.x + gesture.dx;
					const limitX = this.props.width - this.state.imageWidth;
					if (endX > 0) {
						// console.log('left reached', endX);
						endPos = { x: 0, y: 0 };
					} else if (endX < limitX) {
						// console.log('right reached', endX, limitX);
						endPos = { x: limitX, y: 0 };
					} else {
						endPos = { x: endX, y: 0 };
					}
				}
				Animated.spring(this.imagePosition, {
					toValue: endPos,
					useNativeDriver: false,
				}).start();

				if (this.props.onPositionEnd)
					this.props.onPositionEnd({
						x: endPos.x / this.state.imageWidth,
						y: endPos.y / this.state.imageHeight,
					});

				this.setState({ panning: false });
			},
			onPanResponderTerminate: (event, gesture) => {
				this.setState({ panning: false });
			},
		});

		this.state = {
			imageWidth: 0,
			imageHeight: 0,
			imagePanResponder,
			isVertical: true,
			showGuide: false,
			animatedOpacity: new Animated.Value(1),
			panning: false,
		};
	}

	componentDidMount() {
		this.calculateDimensions();
	}

	componentDidUpdate(prevProps) {
		if (prevProps.source.uri !== this.props.source.uri) {
			// console.log('componentDidUpdate', prevProps.source.uri, this.props.source.uri);
			this.calculateDimensions();
		}
	}

	calculateDimensions = () => {
		Image.getSize(this.props.source.uri, (imageWidth, imageHeight) => {
			// Default vertical positioning
			const newWidth = this.props.width;
			const newHeight = imageHeight * (this.props.width / imageWidth);

			if (newHeight < this.props.height) {
				// If vertical positioning isn't possible, enable horizontal positioning
				this.setState(
					{
						imageWidth: imageWidth * (this.props.height / imageHeight),
						imageHeight: this.props.height,
						isVertical: false,
						showGuide: this.props.onPositionEnd ? true : false,
					},
					this.onDimensionAvailable,
				);
			} else {
				this.setState(
					{
						imageWidth: newWidth,
						imageHeight: newHeight,
						isVertical: true,
						showGuide: this.props.onPositionEnd ? true : false,
					},
					this.onDimensionAvailable,
				);
			}
		});
	};

	onDimensionAvailable = () => {
		const { offset } = this.props;
		const { imageWidth, imageHeight, isVertical } = this.state;

		if (offset) {
			// Apply percentage offset
			const actual = {
				x: offset.x * imageWidth,
				y: offset.y * imageHeight,
			};
			this.imagePosition.setValue(actual);
		} else {
			// Centered by default
			this.imagePosition.setValue({
				x: isVertical ? 0 : -0.5 * imageWidth + 0.5 * this.props.width,
				y: isVertical ? -0.5 * imageHeight + 0.5 * this.props.height : 0,
			});
		}

		if (this.props.onPositionEnd) {
			setTimeout(() => {
				Animated.timing(this.state.animatedOpacity, {
					toValue: 0,
					duration: 900,
					useNativeDriver: false,
				}).start(() => {
					this.setState({ showGuide: false });
				});
			}, 1000);
		}
	};

	renderGrid() {
		if (!this.state.panning) return null;
		return (
			<View style={styles.gridContainer}>
				<View style={styles.gridHorizontal} />
				<View style={styles.gridVertical} />
			</View>
		);
	}

	renderGuide() {
		if (!this.state.showGuide) return null;
		const { animatedOpacity, isVertical } = this.state;
		return (
			<Animated.View
				style={[styles.guideContainer, { opacity: animatedOpacity }]}
			>
				<View style={[styles.guideIconContainer, { flexDirection: "column" }]}>
					<Icon
						name="arrow-up"
						type="font-awesome"
						iconStyle={[
							styles.guideIcon,
							!isVertical && styles.guideIconDisabled,
						]}
					/>
					<Icon
						name="arrow-down"
						type="font-awesome"
						iconStyle={[
							styles.guideIcon,
							!isVertical && styles.guideIconDisabled,
						]}
					/>
				</View>
				<View style={[styles.guideIconContainer, { flexDirection: "row" }]}>
					<Icon
						name="arrow-left"
						type="font-awesome"
						iconStyle={[
							styles.guideIcon,
							isVertical && styles.guideIconDisabled,
						]}
					/>
					<Icon
						name="arrow-right"
						type="font-awesome"
						iconStyle={[
							styles.guideIcon,
							isVertical && styles.guideIconDisabled,
						]}
					/>
				</View>
			</Animated.View>
		);
	}

	render() {
		const { imageWidth, imageHeight, imagePanResponder } = this.state;

		return (
			<View
				style={[
					styles.container,
					{ width: this.props.width, height: this.props.height },
					this.props.style,
				]}
			>
				<Animated.Image
					source={this.props.source}
					style={[
						{ width: imageWidth, height: imageHeight },
						this.imagePosition.getLayout(),
					]}
					{...imagePanResponder.panHandlers}
				/>
				{this.renderGrid()}
				{this.renderGuide()}
			</View>
		);
	}
}

const styles = StyleSheet.create({
	container: {
		overflow: "hidden",
		backgroundColor: BOXGREY,
	},
	guideContainer: {
		position: "absolute",
		top: 0,
		right: 0,
		bottom: 0,
		left: 0,
		alignItems: "center",
		justifyContent: "center",
		backgroundColor: "#0006",
	},
	guideIconContainer: {
		position: "absolute",
		top: 0,
		right: 0,
		bottom: 0,
		left: 0,
		alignItems: "center",
		justifyContent: "center",
	},
	guideIcon: {
		color: "#fff",
		fontSize: 50,
		margin: 15,
	},
	guideIconDisabled: {
		color: TEXT_LIGHT,
	},
	gridContainer: {
		position: "absolute",
		top: 0,
		right: 0,
		bottom: 0,
		left: 0,
	},
	gridHorizontal: {
		position: "absolute",
		top: 0,
		right: 0,
		left: 0,
		height: "50%",
		borderBottomWidth: 1,
		borderBottomColor: BOXGREY,
	},
	gridVertical: {
		position: "absolute",
		top: 0,
		right: 0,
		bottom: 0,
		width: "50%",
		borderLeftWidth: 1,
		borderLeftColor: BOXGREY,
	},
});

export default PositionedImage;
