import React, { Component } from "react";
import {
	View,
	Image,
	ImageBackground,
	TouchableOpacity,
	KeyboardAvoidingView,
	Platform,
	ScrollView,
	Alert,
	TextInput,
} from "react-native";
import {
	GiftedChat,
	Bubble,
	MessageText,
	Send,
	InputToolbar,
} from "react-native-gifted-chat";
import { connect } from "react-redux";
import _ from "lodash";
import moment from "moment";
import { Icon } from "@rneui/themed";
import { withSafeAreaInsets } from "react-native-safe-area-context";
import { Spinner } from "./Spinner";
import { ProfilePic } from "./ProfilePic";
import PlussChatTime from "./PlussChatTime";
import { PDFPopup } from "./PDFPopup";
import { Attachment } from "./Attachment";
import PlussChatMessage from "./PlussChatMessage";
import { Text } from ".";
import { ConfirmPopup } from "./ConfirmPopup";
import {
	TEXT_DARK,
	LINEGREY,
	TEXT_DARKEST,
	getMainBrandingColourFromState,
	getLightBrandingColourFromState,
	BG_GREY,
	TEXT_BLUEGREY,
} from "../colours";
import {
	getEnabledTabsFromState,
	get1400,
	getThumb300,
	imageExists,
	isVideo,
	getImageSource,
	getFileName,
} from "../helper";
import Config, { Services } from "../config";
import ImageUploader from "./ImageUploader";
import ImageUploadProgress from "./ImageUploadProgress";
import { ImagePopup } from "./ImagePopup";
import { VideoPopup } from "./VideoPopup";

const IMAGE_SIZE_SMALL = 55;
const IMAGE_SIZE_LARGE = 110;
const IMAGES_PER_ROW = 4;
const IMAGE_MARGIN = 2;
const IMAGE_PREVIEW_AREA_HEIGHT = 105;
const IMAGE_PREVIEW_SIZE = IMAGE_PREVIEW_AREA_HEIGHT - 25;

class PlussChat extends Component {
	constructor(props) {
		super(props);
		const bottomInset = this.props.insets?.bottom ?? 0;
		const isSingleTab = this.props.tabCount === 1 && bottomInset > 0;
		this.MIN_COMPOSER_HEIGHT = Platform.select({
			ios: isSingleTab ? 42 : 33,
			android: 41,
		});

		this.state = {
			currentUser: {
				_id: this.props.user.uid,
				name: this.props.user.displayName,
				avatar:
					!_.isUndefined(this.props.user.profilePic) &&
					!_.isEmpty(this.props.user.profilePic)
						? this.props.user.profilePic
						: Config.env.tinyChatDefault,
			},

			messages: [],
			imagePopupSource: [],
			imagePopupIndex: 0,
			imagePopupOpen: false,
			imagesToUpload: [],
			showFullscreenVideo: false,
			currentVideoUrl: "",
			showDeleteMessageConfirm: false,
			messageToDelete: null,
			composerHeight: this.MIN_COMPOSER_HEIGHT,
		};
		this.checkThumb = null;
	}

	UNSAFE_componentWillMount() {
		this.updateMessages(this.props);
	}

	UNSAFE_componentWillReceiveProps(nextProps) {
		// Only update if messages actually changed
		if (nextProps.messages !== this.props.messages) {
			this.updateMessages(nextProps);
		}
	}

	updateMessages(props) {
		// Only update if messages actually changed
		if (
			!_.isUndefined(props.messages) &&
			!_.isEqual(props.messages, this.state.messages)
		) {
			this.setState({ messages: props.messages });
		}
	}

	/***
	 *
	 * Messaging functionality
	 */
	onSend(messages = []) {
		// if (this.chatKey) {
		//     this.sendMessage(messages[0]);
		// }
	}

	onPressEvent = (event) => {
		Services.navigation.navigate("eventDetail", { event });
	};
	onPressAttachment = (attachment) => {
		switch (attachment.Type) {
			case "Event":
				Services.navigation.navigate("eventDetail", { event: attachment });
				break;
			case "Place":
				Services.navigation.navigate("placeDetail", { place: attachment });
				break;
			default:
				return;
		}
	};

	hasImagesAttached = (imagesToUpload = null) => {
		return !_.isEmpty(imagesToUpload || this.state.imagesToUpload);
	};

	hasImagesReady = (imagesToUpload = null) => {
		const upload = imagesToUpload || this.state.imagesToUpload;
		return (
			this.hasImagesAttached(upload) &&
			upload.every((i) => !i.uploading && i.thumbNailExists)
		);
	};

	waitForThumbnails = () => {
		if (this.checkThumb) return;

		this.checkThumb = setInterval(async () => {
			const imagesToUpload = [];
			await Promise.all(
				this.state.imagesToUpload.map((image) => {
					return new Promise(async (resolve) => {
						const newImage = { ...image };
						imagesToUpload.push(newImage);
						if (newImage.url && !newImage.thumbNailExists) {
							newImage.uploading = false;
							newImage.allowRetry = false;
							newImage.thumbNailExists = await imageExists(
								newImage.thumbNailUrl,
							);
							resolve(newImage.thumbNailExists);
						}
						resolve(true);
					});
				}),
			);
			const thumbnailsExist = imagesToUpload.every(
				(image) => !image.url || image.thumbNailExists,
			);
			if (thumbnailsExist) {
				clearInterval(this.checkThumb);
				this.checkThumb = null;
				this.setState({ imagesToUpload });
			}
		}, 2000);
	};

	onOpenAttachment = (a) => {
		this.setState({
			selectedPDF: a,
		});
	};

	onCloseAttachment = () => {
		this.setState({
			selectedPDF: null,
		});
	};

	showUploadMenu() {
		this.imageUploader.showUploadMenu();
	}

	onFocusInput = () => {
		this.setState({
			keyboardOpen: true,
		});
		if (this.props.keyboardOpen) {
			this.props.keyboardOpen();
		}
	};

	onBlurInput = () => {
		this.setState({
			keyboardOpen: false,
		});
	};

	onUploadStarted = (uploadUri, imageUri) => {
		const imagesToUpload = [
			...this.state.imagesToUpload,
			{
				uploading: true,
				uploadProgress: "0%",
				uploadUri,
				imageUri,
				allowRetry: true,
			},
		];
		this.setState({ imagesToUpload });
	};

	onUploadProgress = (progress) => {
		const imagesToUpload = [...this.state.imagesToUpload];
		imagesToUpload.map((img) => {
			if (img.uploadUri === progress.uri) {
				img.uploadProgress = progress.percentage;
				img.uploading = true;
				img.allowRetry = true;
			}
		});
		this.setState({ imagesToUpload });
	};

	onUploadSuccess = async (uri, uploadUri) => {
		const imagesToUpload = [...this.state.imagesToUpload];
		imagesToUpload.map((img) => {
			if (img.uploadUri === uploadUri && img.uploading) {
				img.url = uri.replace("/general/", "/general1400/");
				img.thumbNailExists = false;
				img.thumbNailUrl = getThumb300(img.url);
				img.allowRetry = true;
			}
		});
		this.setState({ imagesToUpload }, () => this.waitForThumbnails());
	};

	onUploadFailed = (uploadUri) => {
		const imagesToUpload = [...this.state.imagesToUpload];
		imagesToUpload.map((img) => {
			if (img.uploadUri === uploadUri) {
				img.uploading = true; // Requried for retry
				img.uploadProgress = "";
				img.allowRetry = true;
			}
		});
		this.setState({ imagesToUpload });
	};

	onLibrarySelected = (uri) => {
		const imagesToUpload = [
			...this.state.imagesToUpload,
			{
				uploading: false,
				allowRetry: false,
				url: get1400(uri),
				thumbNailExists: true,
				thumbNailUrl: getThumb300(uri),
			},
		];
		this.setState({ imagesToUpload });
	};

	onPressImage = (images, selected) => {
		this.setState({
			imagePopupSource: images,
			imagePopupIndex: images.indexOf(selected),
			imagePopupOpen: true,
		});
	};

	onReply = (message) => {
		this.setState({
			replyingTo: message,
		});
	};

	onDelete = (message) => {
		// Only proceed if delete handler is provided
		if (!this.props.onDeleteMessage) {
			return;
		}

		// Only allow deletion of own messages
		if (message.user._id !== this.props.user.uid) {
			return;
		}

		this.setState({
			showDeleteMessageConfirm: true,
			messageToDelete: message,
		});
	};

	onCancelDeleteMessage = () => {
		this.setState({
			showDeleteMessageConfirm: false,
			messageToDelete: null,
		});
	};

	onConfirmDeleteMessage = async () => {
		const { messageToDelete } = this.state;
		if (!messageToDelete) return;

		this.setState({
			showDeleteMessageConfirm: false,
		});

		try {
			// Call the parent's delete handler if provided
			if (this.props.onDeleteMessage) {
				await this.props.onDeleteMessage(messageToDelete);
			}

			this.setState({
				messageToDelete: null,
			});
		} catch (error) {
			// Handle error gracefully if parent handler fails
			console.log("onConfirmDeleteMessage error", error);
			// Error is already handled by parent component
			this.setState({ messageToDelete: null });
		}
	};

	closeGallery() {
		this.setState({
			imagePopupSource: [],
			imagePopupIndex: 0,
			imagePopupOpen: false,
		});
	}

	onRemoveImage = (url) => {
		const imagesToUpload = this.state.imagesToUpload.filter(
			(image) => image.url !== url,
		);
		this.setState({ imagesToUpload });
	};

	toggleFullscreenVideo = (url) => {
		if (typeof url !== "string") url = "";
		this.setState({
			showFullscreenVideo: url.length > 0,
			currentVideoUrl: url,
		});
	};

	sendMessages(messages) {
		if (this.hasImagesAttached()) {
			// Don't allow send if attached images aren't ready
			if (!this.hasImagesReady()) return;
			messages[0].image = this.state.imagesToUpload.map((image) => image.url);
		}
		if (_.isEmpty(messages[0].text)) {
			messages[0].text = "";
		}
		if (!messages[0].text && !messages[0].image) return;

		if (this.state.replyingTo) {
			messages[0].replyingTo = this.state.replyingTo;
		}

		this.props.onSend(messages);
		this.setState({ imagesToUpload: [], replyingTo: null });
	}

	/**
	 *
	 * Render Functions
	 */
	renderBubble(bubbleProps) {
		const wrapperStyle = {};
		if (
			!_.isEmpty(bubbleProps.currentMessage.text) &&
			!_.isEmpty(bubbleProps.currentMessage.image)
		) {
			wrapperStyle.paddingTop = 8;
			wrapperStyle.paddingBottom = 16;
			wrapperStyle.minWidth = 142; // 110 image width + 16 padding either side
		}
		if (!_.isEmpty(bubbleProps.currentMessage.attachments)) {
			wrapperStyle.paddingTop = 8;
			wrapperStyle.paddingBottom = 16;
			wrapperStyle.paddingHorizontal = 16;
		}
		return (
			<Bubble
				{...bubbleProps}
				renderMessageImage={() => null}
				isCustomViewBottom={true}
				wrapperStyle={{
					left: {
						backgroundColor: LINEGREY,
						borderRadius: 25,
						...wrapperStyle,
					},
					right: {
						backgroundColor: this.props.colourBrandingLight,
						borderRadius: 25,
						...wrapperStyle,
					},
				}}
				containerToNextStyle={{
					left: {
						borderBottomLeftRadius: 5,
					},
					right: {
						borderBottomRightRadius: 5,
					},
				}}
				containerToPreviousStyle={{
					left: {
						borderTopLeftRadius: 5,
					},
					right: {
						borderTopRightRadius: 5,
					},
				}}
			/>
		);
	}
	renderMessage(props) {
		return (
			<PlussChatMessage
				key={props.RowId}
				colourBrandingMain={this.props.colourBrandingMain}
				onPressReply={() => {
					this.onReply(props.currentMessage);
				}}
				onPressDelete={
					this.props.onDeleteMessage
						? () => {
								this.onDelete(props.currentMessage);
							}
						: null
				}
				{...props}
			/>
		);
	}
	renderMessageText(messageTextProps) {
		// If message is deleted, show placeholder text
		const props = messageTextProps.currentMessage.deleted
			? {
					...messageTextProps,
					currentMessage: {
						...messageTextProps.currentMessage,
						text: "[Message deleted]",
					},
				}
			: messageTextProps;

		return (
			<MessageText
				{...props}
				textStyle={{
					left: {
						fontFamily: "sf-regular",
						fontSize: 16,
						color: TEXT_DARKEST,
						marginTop: 10,
						marginBottom: 10,
						marginLeft: 15,
						marginRight: 15,
					},
					right: {
						fontFamily: "sf-regular",
						fontSize: 16,
						color: this.props.colourBrandingMain,
						marginTop: 10,
						marginBottom: 10,
						marginLeft: 15,
						marginRight: 15,
					},
				}}
				linkStyle={{
					left: {
						color: TEXT_DARKEST,
					},
					right: {
						color: this.props.colourBrandingMain,
					},
				}}
				textProps={{
					selectable: true,
				}}
			/>
		);
	}
	renderTime() {
		return null;
	}
	renderDay(dayProps) {
		return (
			<PlussChatTime
				{...dayProps}
				textStyle={{
					fontFamily: "sf-semibold",
					color: TEXT_DARK,
					fontSize: 12,
				}}
			/>
		);
	}
	renderCustomView({ currentMessage, position }) {
		// Don't show images or attachments for deleted messages
		if (currentMessage.deleted) {
			return null;
		}

		if (currentMessage.image) {
			const images =
				typeof currentMessage.image === "string"
					? [currentMessage.image]
					: currentMessage.image;
			const containerWidth = (() => {
				if (images.length === 0) return 0;
				if (images.length === 1) return IMAGE_SIZE_LARGE;
				if (images.length <= IMAGES_PER_ROW)
					return (IMAGE_SIZE_SMALL + IMAGE_MARGIN) * images.length;
				return (IMAGE_SIZE_SMALL + IMAGE_MARGIN) * IMAGES_PER_ROW;
			})();
			return (
				<View
					style={[
						styles.imagesContainer,
						{
							width: containerWidth,
							paddingVertical: currentMessage.text ? 0 : 20,
						},
					]}
				>
					{images.map((img) => {
						const thumb = getThumb300(img);
						if (isVideo(img)) {
							return (
								<TouchableOpacity
									key={thumb}
									onPress={this.toggleFullscreenVideo.bind(this, img)}
								>
									<ImageBackground
										style={
											images.length > 1
												? styles.messageImageSmall
												: styles.messageImageLarge
										}
										source={{ uri: thumb }}
									>
										<View style={styles.imagePlayContainer}>
											<Icon
												name="play"
												type="font-awesome"
												iconStyle={styles.imageControlIcon}
											/>
										</View>
									</ImageBackground>
								</TouchableOpacity>
							);
						}
						return (
							<TouchableOpacity
								key={thumb}
								onPress={() => this.onPressImage(images, img)}
							>
								<Image
									source={{ uri: thumb }}
									style={
										images.length > 1
											? styles.messageImageSmall
											: styles.messageImageLarge
									}
								/>
							</TouchableOpacity>
						);
					})}
				</View>
			);
		}
		if (!_.isEmpty(currentMessage.attachments)) {
			return (
				<View>
					{currentMessage.attachments.map((url, i) => {
						return (
							<Attachment
								onPress={() => {
									this.onOpenAttachment(url);
								}}
								key={i}
								title={getFileName(url)}
							/>
						);
					})}
				</View>
			);
		}
		if (currentMessage.event) {
			return (
				<TouchableOpacity
					onPress={this.onPressEvent.bind(this, currentMessage.event)}
				>
					<View style={styles.eventContainer[position]}>
						<Image
							style={[styles.eventImage, styles.eventImageMargin[position]]}
							source={{ uri: currentMessage.event.Thumbnail }}
						/>
						<View style={styles.eventInfo}>
							<Text
								numberOfLines={3}
								style={[
									styles.eventTitle,
									styles.eventInfoAlign[position],
									{ color: this.props.colourBrandingMain },
								]}
							>
								{currentMessage.event.Title}
							</Text>
							<Text
								style={[
									styles.eventDate,
									styles.eventInfoAlign[position],
									{ color: this.props.colourBrandingMain },
								]}
							>
								{moment
									.utc(currentMessage.event.StartTime)
									.local()
									.format("ddd D MMM")}
							</Text>
						</View>
					</View>
				</TouchableOpacity>
			);
		}
		if (currentMessage.attachment) {
			return (
				<TouchableOpacity
					onPress={this.onPressAttachment.bind(this, currentMessage.attachment)}
				>
					<View style={styles.eventContainer[position]}>
						<Image
							style={[styles.eventImage, styles.eventImageMargin[position]]}
							source={{ uri: currentMessage.attachment.Thumbnail }}
						/>
						<View style={styles.eventInfo}>
							<Text
								numberOfLines={3}
								style={[
									styles.eventTitle,
									styles.eventInfoAlign[position],
									{ color: this.props.colourBrandingMain },
								]}
							>
								{currentMessage.attachment.Title}
							</Text>
							{currentMessage.attachment.StartTime && (
								<Text
									style={[
										styles.eventDate,
										styles.eventInfoAlign[position],
										{ color: this.props.colourBrandingMain },
									]}
								>
									{moment
										.utc(currentMessage.attachment.StartTime)
										.local()
										.format("ddd D MMM")}
								</Text>
							)}
						</View>
					</View>
				</TouchableOpacity>
			);
		}
		return null;
	}

	renderSend(props) {
		const buttonTopOffset = this.state.replyingTo ? 46 : 4;
		const showSendButton =
			!_.isEmpty(props.text) || this.hasImagesReady(props.imagesToUpload);
		return (
			<View
				style={{
					position: "absolute",
					top: buttonTopOffset,
					right: 8,
					flexDirection: "row",
					alignItems: "center",
				}}
			>
				{/* Image upload button - always visible */}
				<TouchableOpacity
					onPress={this.showUploadMenu.bind(this)}
					style={[
						styles.sendContainer,
						{
							right:
								_.isEmpty(props.text) &&
								!this.hasImagesReady(props.imagesToUpload)
									? 0
									: this.MIN_COMPOSER_HEIGHT,

							width: this.MIN_COMPOSER_HEIGHT,
							height: this.MIN_COMPOSER_HEIGHT,
						},
					]}
				>
					<Icon
						name={"picture-o"}
						type="font-awesome"
						iconStyle={[styles.send, { width: this.MIN_COMPOSER_HEIGHT }]}
					/>
				</TouchableOpacity>

				{/* Send button - only visible when there's text or images */}
				{showSendButton && (
					<Send
						{...props}
						alwaysShowSend={true}
						onSend={props.onSend}
						text={props.text || " "}
						containerStyle={[
							styles.sendContainer,
							{
								width: this.MIN_COMPOSER_HEIGHT,
								height: this.MIN_COMPOSER_HEIGHT,
							},
						]}
					>
						<Icon
							name={"paper-plane"}
							type="font-awesome"
							iconStyle={[styles.send, { width: this.MIN_COMPOSER_HEIGHT }]}
						/>
					</Send>
				)}
			</View>
		);
	}

	renderAccessory(props) {
		const hasAttachment = this.hasImagesAttached(props.imagesToUpload);
		if (!hasAttachment) {
			return null;
		}
		return (
			<ScrollView horizontal style={styles.uploadImagesContainer}>
				{props.imagesToUpload.map((image) => {
					if (image.uploading) {
						return (
							<ImageUploadProgress
								key={image.uploadUri}
								uploader={this.imageUploader}
								image={image}
								color={this.props.colourBrandingMain}
								style={{ width: IMAGE_PREVIEW_SIZE, marginRight: 10 }}
								progressTextStyle={{ fontSize: 10 }}
							/>
						);
					}
					const isVideoUrl = isVideo(image.url);
					return (
						<View key={image.url} style={styles.accessoryImageContainer}>
							<ImageBackground
								style={styles.accessoryImage}
								imageStyle={styles.accessoryImageBorder}
								source={getImageSource(
									image.thumbNailExists ? image.thumbNailUrl : image.url,
								)}
							>
								{isVideoUrl && (
									<View style={styles.imagePlayContainer}>
										<TouchableOpacity
											onPress={this.toggleFullscreenVideo.bind(this, image.url)}
										>
											<Icon
												name="play"
												type="font-awesome"
												iconStyle={styles.imageControlIcon}
											/>
										</TouchableOpacity>
									</View>
								)}
							</ImageBackground>
							<TouchableOpacity
								style={styles.previewItemRemoveButton}
								onPress={() => this.onRemoveImage(image.url)}
								hitSlop={{ top: 8, right: 8, bottom: 8, left: 8 }}
							>
								<View
									style={[
										styles.previewItemRemoveContainer,
										{ backgroundColor: this.props.colourBrandingMain },
									]}
								>
									<Icon
										name="times"
										type="font-awesome"
										iconStyle={styles.previewItemRemoveIcon}
									/>
								</View>
							</TouchableOpacity>
						</View>
					);
				})}
			</ScrollView>
		);
	}

	renderInputToolbar(props) {
		const hasAttachment = this.hasImagesAttached(props.imagesToUpload);
		return (
			<InputToolbar
				{...props}
				containerStyle={styles.inputContainer}
				renderComposer={this.renderComposer.bind(this)}
				renderAccessory={hasAttachment ? this.renderAccessory.bind(this) : null}
				accessoryStyle={hasAttachment && styles.accessory}
			/>
		);
	}
	renderFooter() {
		// if (this.state.keyboardOpen) {
		//     return null;
		// }
		// fixes an issue where there's no gap between bottom message and reply container
		return <View style={{ height: 10 }} />;
	}
	renderLoading() {
		return (
			<View
				style={{
					marginTop: 15,
					justifyContent: "center",
					alignContent: "center",
				}}
			>
				<Spinner size={"small"} color={this.props.colourBrandingMain} />
			</View>
		);
	}
	renderAvatar(props) {
		return (
			<View style={{ marginRight: 2 }}>
				<ProfilePic
					ProfilePic={props.currentMessage.user.avatar}
					Diameter={28}
				/>
			</View>
		);
	}
	renderComposer(props) {
		return (
			<View style={{ width: "100%" }}>
				{/* Replying to section - stacked vertically on top */}
				{this.state.replyingTo && (
					<View style={styles.replyingTo}>
						<Text type="body">
							Replying to{" "}
							{_.isEmpty(this.state.replyingTo?.user?.name)
								? "message"
								: this.state.replyingTo?.user?.name}
						</Text>
						<TouchableOpacity
							style={styles.replyingRemoveButton}
							onPress={() => this.onReply(null)}
							hitSlop={{ top: 8, right: 8, bottom: 8, left: 8 }}
						>
							<View
								style={[
									styles.replyingRemoveContainer,
									{ backgroundColor: this.props.colourBrandingMain },
								]}
							>
								<Icon
									name="times"
									type="font-awesome"
									iconStyle={styles.replyingRemoveIcon}
								/>
							</View>
						</TouchableOpacity>
					</View>
				)}
				{/* Horizontal row for input - buttons are absolutely positioned via renderSend */}
				<View
					style={{
						flexDirection: "row",
						alignItems: "flex-end",
						width: "100%",
						paddingBottom: 8,
					}}
				>
					<View
						style={[
							styles.input,
							{
								flex: 1,
								marginRight:
									_.isEmpty(props.text) &&
									!this.hasImagesReady(props.imagesToUpload)
										? 16 + this.MIN_COMPOSER_HEIGHT
										: 2 * (this.MIN_COMPOSER_HEIGHT + 8),
								paddingHorizontal: 12,
								paddingVertical: Platform.select({ ios: 8, android: 6 }),
							},
						]}
					>
						<TextInput
							maxFontSizeMultiplier={1.2}
							placeholder="Type a message..."
							multiline
							value={props.text}
							onChangeText={props.onTextChanged}
							style={[
								styles.inputText,
								{
									lineHeight: 20,
									minHeight: this.MIN_COMPOSER_HEIGHT - 16,
									maxHeight: 100,
								},
							]}
							onFocus={this.onFocusInput.bind(this)}
							onBlur={this.onBlurInput.bind(this)}
							placeholderTextColor="#999"
						/>
					</View>
				</View>
			</View>
		);
	}

	/***
	 * Main Render
	 */
	renderChat() {
		const minInputToolbarHeight =
			this.MIN_COMPOSER_HEIGHT +
			32 +
			(this.state.replyingTo ? 38 : 0) +
			(this.hasImagesAttached() ? IMAGE_PREVIEW_AREA_HEIGHT : 0);

		return (
			<GiftedChat
				isKeyboardInternallyHandled={false}
				alwaysShowSend={false}
				keyboardShouldPersistTaps={"never"}
				renderAvatarOnTop
				minInputToolbarHeight={minInputToolbarHeight}
				minComposerHeight={this.MIN_COMPOSER_HEIGHT}
				bottomOffset={0}
				onSend={this.sendMessages.bind(this)}
				messages={this.state.messages}
				user={this.state.currentUser}
				renderBubble={this.renderBubble.bind(this)}
				renderMessage={this.renderMessage.bind(this)}
				renderMessageText={this.renderMessageText.bind(this)}
				renderTime={this.renderTime.bind(this)}
				renderDay={this.renderDay.bind(this)}
				renderCustomView={this.renderCustomView.bind(this)}
				renderSend={this.renderSend.bind(this)}
				renderInputToolbar={this.renderInputToolbar.bind(this)}
				renderFooter={this.renderFooter.bind(this)}
				renderLoading={this.renderLoading.bind(this)}
				renderAvatar={this.renderAvatar.bind(this)}
				imagesToUpload={this.state.imagesToUpload}
			/>
		);
	}

	renderImageUploader() {
		return (
			<ImageUploader
				ref={(ref) => (this.imageUploader = ref)}
				onUploadStarted={this.onUploadStarted}
				onUploadProgress={this.onUploadProgress}
				onUploadSuccess={this.onUploadSuccess}
				onUploadFailed={this.onUploadFailed}
				onLibrarySelected={this.onLibrarySelected}
				quality={0.8}
				allowsEditing={false}
				fileName={"imageInput"}
				popupTitle={"Add Image"}
				userId={this.props.user.uid}
				multiple
				allowVideo
			/>
		);
	}

	renderImagePopup() {
		const { imagePopupOpen, imagePopupSource, imagePopupIndex } = this.state;
		return (
			<ImagePopup
				visible={imagePopupOpen}
				images={imagePopupSource}
				index={imagePopupIndex}
				onClose={this.closeGallery.bind(this)}
			/>
		);
	}

	renderVideoPlayerPopup() {
		const { showFullscreenVideo, currentVideoUrl } = this.state;
		if (!currentVideoUrl) return;

		return (
			<VideoPopup
				uri={currentVideoUrl}
				visible={showFullscreenVideo}
				onClose={this.toggleFullscreenVideo}
			/>
		);
	}

	renderPDF() {
		if (_.isEmpty(this.state.selectedPDF)) {
			return null;
		}
		return (
			<PDFPopup
				source={this.state.selectedPDF}
				onClose={this.onCloseAttachment}
				title={getFileName(this.state.selectedPDF)}
				pdfCount={1}
			/>
		);
	}

	renderDeleteConfirmPopup() {
		return (
			<ConfirmPopup
				visible={this.state.showDeleteMessageConfirm}
				onConfirm={this.onConfirmDeleteMessage}
				onCancel={this.onCancelDeleteMessage}
				text="Are you sure you want to delete this message?"
				yesText="Delete"
				noText="Cancel"
			/>
		);
	}

	render() {
		return (
			<KeyboardAvoidingView behavior="padding" style={styles.chatContainer}>
				{this.renderChat()}
				{this.renderImageUploader()}
				{this.renderImagePopup()}
				{this.renderVideoPlayerPopup()}
				{this.renderPDF()}
				{this.renderDeleteConfirmPopup()}
			</KeyboardAvoidingView>
		);
	}
}

const styles = {
	chatContainer: {
		flex: 1,
		justifyContent: "center",
	},
	eventContainer: {
		left: {
			paddingTop: 5,
			paddingLeft: 15,
			paddingRight: 15,
			paddingBottom: 5,
			flexDirection: "row",
		},
		right: {
			paddingTop: 5,
			paddingLeft: 15,
			paddingRight: 15,
			paddingBottom: 5,
			flexDirection: "row-reverse",
		},
	},
	eventImage: {
		width: 80,
		height: 80,
		resizeMode: "cover",
		borderRadius: 2,
	},
	eventImageMargin: {
		right: {
			marginLeft: 15,
		},
		left: {
			marginRight: 15,
		},
	},
	eventInfo: {
		minHeight: 80,
		width: 150,
	},
	eventTitle: {
		fontSize: 12,
		fontFamily: "sf-bold",
		backgroundColor: "rgba(255,255,255,0)",
	},
	eventInfoAlign: {
		left: {
			textAlign: "left",
		},
		right: {
			textAlign: "right",
		},
	},
	messageImageLarge: {
		width: IMAGE_SIZE_LARGE,
		height: IMAGE_SIZE_LARGE,
		borderRadius: 2,
		alignSelf: "center",
	},
	messageImageSmall: {
		width: IMAGE_SIZE_SMALL,
		height: IMAGE_SIZE_SMALL,
		borderRadius: 2,
		alignSelf: "center",
		marginRight: IMAGE_MARGIN,
		marginBottom: IMAGE_MARGIN,
	},
	eventDate: {
		fontSize: 12,
		fontFamily: "sf-regular",
		backgroundColor: "rgba(255,255,255,0)",
	},
	inputContainer: {
		backgroundColor: "#fff",
		paddingVertical: 8,
		paddingHorizontal: 8,
	},
	inputText: {
		color: TEXT_DARKEST,
		fontSize: 14,
		fontFamily: "sf-medium",
	},
	input: {
		margin: 0,
		backgroundColor: BG_GREY,
		borderRadius: 5,
		flex: 1,
	},
	composerContainer: {
		flex: 1,
	},
	composerInputWrapper: {
		flex: 1,
		flexDirection: "row",
	},
	replyingTo: {
		minHeight: 30,
		flexDirection: "row",
		alignItems: "center",
		borderBottomWidth: 1,
		borderBottomColor: LINEGREY,
		marginBottom: 8,
	},
	replyingRemoveButton: {
		marginLeft: 10,
	},
	replyingRemoveContainer: {
		justifyContent: "center",
		alignItems: "center",
		borderRadius: 10,
		width: 20,
		height: 20,
		borderWidth: 2,
		borderColor: "#fff",
	},
	replyingRemoveIcon: {
		fontSize: 10,
		color: "#fff",
		marginBottom: 1,
	},
	sendContainer: {
		position: "absolute",
		top: 0,
		right: 0,
		height: 30,
		width: 30,
		alignItems: "center",
		justifyContent: "center",
		backgroundColor: "#fff",
	},
	send: {
		fontSize: 15,
		color: TEXT_BLUEGREY,
		fontSize: 24,
		textAlign: "center",
	},
	accessory: {
		height: IMAGE_PREVIEW_AREA_HEIGHT,
		borderTopWidth: 1,
		borderTopColor: LINEGREY,
		paddingTop: 8,
		marginTop: 8,
	},
	accessoryImageContainer: {
		paddingRight: 8,
		paddingTop: 8,
		marginRight: 5,
	},
	accessoryImage: {
		width: IMAGE_PREVIEW_SIZE,
		height: IMAGE_PREVIEW_SIZE,
	},
	accessoryImageBorder: {
		borderRadius: 2,
	},
	settingDropDownOpen: {
		height: "auto",
	},
	imagesContainer: {
		marginLeft: 10,
		marginRight: 10,
		flexDirection: "row",
		flexWrap: "wrap",
	},
	uploadImagesContainer: {
		flexDirection: "row",
		overflow: "visible",
	},
	previewItemRemoveButton: {
		position: "absolute",
		top: 0,
		right: 0,
	},
	previewItemRemoveContainer: {
		justifyContent: "center",
		alignItems: "center",
		borderRadius: 10,
		width: 20,
		height: 20,
		borderWidth: 2,
		borderColor: "#fff",
	},
	previewItemRemoveIcon: {
		fontSize: 10,
		color: "#fff",
		marginBottom: 1,
	},
	imagePlayContainer: {
		position: "absolute",
		top: 0,
		left: 0,
		right: 0,
		bottom: 0,
		alignItems: "center",
		justifyContent: "center",
	},
	imageControlIcon: {
		color: "#fff",
		fontSize: 20,
		textShadowColor: "rgba(0,0,0,0.3)",
		textShadowOffset: { width: 2, height: 2 },
	},
};

const mapStateToProps = (state) => {
	return {
		user: state.user,
		colourBrandingMain: getMainBrandingColourFromState(state),
		colourBrandingLight: getLightBrandingColourFromState(state),
		tabCount: getEnabledTabsFromState(state).length,
	};
};

export default connect(mapStateToProps, {})(withSafeAreaInsets(PlussChat));
