import React, { Component } from "react";
import { Text } from "@plusscommunities/pluss-core-app/components";
import {
	Platform,
	Linking,
	StyleSheet,
	View,
	TouchableOpacity,
	ScrollView,
} from "react-native";
import { connect } from "react-redux";
import _ from "lodash";
import * as Calendar from "expo-calendar";
import { TEXT_DARK, getMainBrandingColourFromState } from "../colours";
import { InlineButton } from "./InlineButton";
import { Popup } from "./Popup";
import { MiddlePopup } from "./MiddlePopup";

const DEFAULT_TITLE = "Add to Calendar";
const ERROR_EVENT_ADD = "There was a problem adding a calendar event.";

// Required: eventToAdd
// Documentation: https://docs.expo.dev/versions/latest/sdk/calendar/#event
class AddToCalendarButton extends Component {
	constructor(props) {
		super(props);

		this.state = {
			showPermissionWarning: false,
			calendars: null,
			message: null,
		};
	}

	showWarningPopup = () => {
		if (Platform.OS !== "ios") return;
		this.setState({ showPermissionWarning: true });
	};

	closeWarningPopup = () => {
		this.setState({ showPermissionWarning: false });
	};

	goToPermissionSettings = () => {
		Linking.openURL("app-settings:");
		this.setState({ showPermissionWarning: false });
	};

	onAdd = async () => {
		if (!this.props.eventToAdd) {
			this.setState({ message: "There is no event to add" });
			return;
		}

		const { status } = await Calendar.requestCalendarPermissionsAsync();
		if (status !== "granted") {
			this.showWarningPopup();
		} else {
			let calendars = await Calendar.getCalendarsAsync(
				Calendar.EntityTypes.EVENT,
			);
			// console.log('all calendars', calendars);
			if (calendars && calendars.length > 0) {
				calendars = calendars
					.filter((c) => c.allowsModifications)
					.map((c) => {
						return {
							id: c.id,
							title: c.title,
							source: c.source.name,
							color: c.color,
							type: c.type,
						};
					});
				calendars = _.orderBy(calendars, ["source", "title"]);
				// console.log('sorted calendars', calendars);
			}
			this.setState({ calendars });
		}
	};

	onCloseCalendars = () => {
		this.setState({ calendars: null });
	};

	onSelectCalendar = async (calendar) => {
		try {
			const { eventToAdd } = this.props;
			if (!eventToAdd) return;

			const eventId = await Calendar.createEventAsync(calendar.id, eventToAdd);

			this.setState({
				calendars: null,
				message: eventId
					? `${eventToAdd.title} was added to ${calendar.title} successfully.`
					: ERROR_EVENT_ADD,
			});
		} catch (error) {
			console.log("onSelectCalendar", error);
			this.setState({ calendars: null, message: ERROR_EVENT_ADD });
		}
	};

	onCloseMessage = () => {
		this.setState({ message: null });
	};

	renderPermission() {
		return (
			<Popup
				title="Permissions missing"
				text="You must grant access to the Calendars. Tap Go to settings to change your permission settings."
				options={[
					{
						text: "Go to settings",
						action: this.goToPermissionSettings,
						bold: true,
					},
					{
						text: "Ignore",
						action: this.closeWarningPopup,
					},
				]}
			/>
		);
	}

	renderCalendars(calendars) {
		return (
			<MiddlePopup
				style={[styles.calendarsPopup, { height: calendars.length * 60 + 120 }]}
				onClose={this.onCloseCalendars}
			>
				<Text style={styles.calendarPopupTitle}>Select Calendar</Text>
				<View style={styles.calendarPopupContainer}>
					<ScrollView style={{ flex: 1 }} showsVerticalScrollIndicator={false}>
						{calendars.map((cal) => {
							return (
								<TouchableOpacity
									key={cal.id}
									onPress={() => this.onSelectCalendar(cal)}
								>
									<View
										style={[
											styles.calendarContainer,
											{ backgroundColor: cal.color },
										]}
									>
										<Text
											style={styles.calendarText}
										>{`${cal.source}${cal.source === cal.title ? "" : `\n${cal.title}`}`}</Text>
									</View>
								</TouchableOpacity>
							);
						})}
					</ScrollView>
					<TouchableOpacity key={"cancel"} onPress={this.onCloseCalendars}>
						<View
							style={[
								styles.calendarContainer,
								{
									marginTop: 20,
									backgroundColor: this.props.colourBrandingMain,
								},
							]}
						>
							<Text style={styles.calendarText}>Cancel</Text>
						</View>
					</TouchableOpacity>
				</View>
			</MiddlePopup>
		);
	}

	renderMessage(message) {
		return (
			<Popup
				title="Add to Calendar"
				text={message}
				options={[
					{
						text: "Ok",
						action: this.onCloseMessage,
					},
				]}
			/>
		);
	}

	render() {
		const { showPermissionWarning, calendars, message } = this.state;

		if (showPermissionWarning) return this.renderPermission();
		if (calendars && calendars.length > 0)
			return this.renderCalendars(calendars);
		if (message) return this.renderMessage(message);

		return (
			<InlineButton {...this.props} onPress={this.onAdd}>
				{this.props.children || DEFAULT_TITLE}
			</InlineButton>
		);
	}
}

const styles = StyleSheet.create({
	calendarsPopup: {
		width: 250,
		maxHeight: 400,
		padding: 16,
		borderRadius: 12,
	},
	calendarPopupTitle: {
		fontFamily: "sf-bold",
		color: TEXT_DARK,
		fontSize: 18,
		marginBottom: 16,
	},
	calendarPopupContainer: {
		flex: 1,
		justifyContent: "space-between",
	},
	calendarContainer: {
		flexDirection: "row",
		alignItems: "center",
		width: 200,
		height: 40,
		paddingHorizontal: 8,
		borderRadius: 4,
		marginBottom: 10,
	},
	calendarText: {
		color: "#fff",
		textAlign: "center",
		fontFamily: "sf-semibold",
		fontSize: 13,
		flex: 1,
	},
});

const mapStateToProps = (state) => {
	return {
		colourBrandingMain: getMainBrandingColourFromState(state),
	};
};

const button = connect(mapStateToProps, {})(AddToCalendarButton);
export { button as AddToCalendarButton };
