import React, { Component } from 'react';
import _ from 'lodash';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { submit, isSubmitting, SubmissionError } from 'redux-form';
import { View, Alert, StyleSheet } from 'react-native';
import { Dialogue, ActionSheet, NixplayIcon, Text } from 'nixplay-ui-kit';
import { ModalNameForm } from '~comp/Forms/modalNameForm';
import { ModalForm } from '~comp/Forms/modalForm';
import { Form } from '~comp/reduxForm';

import i18n from '~/locale/i18n';
import { store } from '~/store/store';
import { analytics } from '~/lib/utils';

import {
	CREATE_PLAYLIST,
	RENAME_PLAYLIST,
	DELETE_PLAYLIST,
	DELETE_SHARED_PLAYLIST,
	LEAVE_SHARED_PLAYLIST,
	REMOVE_PLAYLIST_CONTENT,
	REMOVE_SHARED_PLAYLIST_AUDIENCE,
	REMOVE_SHARED_PLAYLIST_CONTENT,
	SHOW_TOAST_ERROR,
	SET_PLAYLIST_SORT,
	START_REORDERING_PHOTOS_IN_PLAYLIST,
} from '~/store/actionTypes';
import { PLAYLIST_SORT } from '~/store/contentsConstants';


const styles = StyleSheet.create({
	sortActions: {
		flexDirection: 'row',
		justifyContent: 'center',
		alignItems: 'center',
		paddingHorizontal: 44,
	},
	sortActionIcon: {
		marginLeft: 4,
	},
	sortActionCheckmark: {
		position: 'absolute',
		right: 16,
	},
});

export class PlaylistActionsComponent extends Component {
	static propTypes = {
		actions: PropTypes.array,
		route: PropTypes.string.isRequired,
		deleteFormMeta: PropTypes.object.isRequired,
		submitDeleteForm: PropTypes.func.isRequired,
		changeSorting: PropTypes.func.isRequired,
		isConnected: PropTypes.bool.isRequired,
		toastError: PropTypes.func.isRequired,
		setReorderingPhotosStatus: PropTypes.func.isRequired,
		playlist: PropTypes.shape({
			sortOrder: PropTypes.string,
		}),
		contentSeqChanged: PropTypes.bool,
	}

	static defaultProps = {
		actions: [
			CREATE_PLAYLIST,
			RENAME_PLAYLIST,
			DELETE_PLAYLIST,
			DELETE_SHARED_PLAYLIST,
			LEAVE_SHARED_PLAYLIST,
		],
		playlist: {
			sortOrder: 'MOST_RECENTLY_ADDED',
		},
		contentSeqChanged: false,
	}

	constructor(props) {
		super(props);

		const sortOptions = [{
			label: i18n.t('common.mostRecentlyAdded'),
			value: PLAYLIST_SORT.MOST_RECENTLY_ADDED,
		}, {
			label: i18n.t('common.leastRecentlyAdded'),
			value: PLAYLIST_SORT.LEAST_RECENTLY_ADDED,
		}];

		this.state = {
			selectedAction: '',
			selectedPlaylistId: -1,
			selectedPlaylistName: '',
			selectedContributor: '',
			contributorsListLength: 0,
			additionalParams: {},
			onActionSuccess: () => {},
			sortOptions,
			nextSortOption: '',
		};

		this.dialogue = this.dialogue.bind(this);
		this.doAction = this.doAction.bind(this);
		this.closeAction = this.closeAction.bind(this);
		this.submitActionForm = this.submitActionForm.bind(this);
		this.actionExists = this.actionExists.bind(this);

		this.onSubmitFail = (errors) => {
			const { _error: error } = errors;
			this.props.toastError({
				text: typeof error.toString === 'function' ? error.toString() : error,
			});
		};
	}

	dialogue(action) {
		switch (action) {
			case DELETE_PLAYLIST:
				analytics.logAction('open_playlist_delete');
				return this.deleteDialogue;
			case DELETE_SHARED_PLAYLIST:
				analytics.logAction('open_shared_playlist_delete');
				return this.deleteSharedDialogue;
			case REMOVE_PLAYLIST_CONTENT:
				analytics.logAction('open_playlist_delete_content');
				return this.removeContentDialogue;
			case SET_PLAYLIST_SORT:
				analytics.logAction('open_playlist_sort');
				return this.sortPicker;
			case LEAVE_SHARED_PLAYLIST:
				return this.leaveSharedPlaylistDialogue;
			case REMOVE_SHARED_PLAYLIST_AUDIENCE:
				return this.removeAudienceDialouge;
			case REMOVE_SHARED_PLAYLIST_CONTENT:
				return this.removeSharedPlaylistContentDialouge;
			default:
				analytics.logAction('open_playlist_rename');
				return this.modalNameForm;
		}
	}

	doAction(action, playlistId, additionalParams, onActionSuccess) {
		if (this.props.actions.indexOf(action) < 0) return;
		this.setState({
			selectedAction: action,
			selectedPlaylistId: playlistId,
			selectedPlaylistName: additionalParams.name,
			selectedContributor: additionalParams.contributorName,
			contributorsListLength: additionalParams.contributorLength,
			isShared: additionalParams.shared,
			additionalParams,
			onActionSuccess,
		}, () => {
			if (action === SET_PLAYLIST_SORT) {
				this.processSortOptions(() => this.dialogue(action).open());
			} else {
				this.dialogue(action).open();
			}
		});
	}

	closeAction(callback) {
		this.dialogue(this.state.selectedAction).close();
		this.setState({
			selectedAction: '',
			selectedPlaylistId: -1,
			selectedPlaylistName: '',
			selectedContributor: '',
			additionalParams: {},
			onActionSuccess: () => {},
		}, () => {
			if (typeof callback === 'function') callback();
		});
	}

	submitActionForm(values, dispatch) {
		const { playlists } = store.getState();
		return new Promise((resolve, reject) => {
			if (this.props.isConnected) {
			/**
			 * Validate pre-existing playlist name
			 */
				if (!_.find(playlists.playlists, _.matchesProperty('name', values.name))) {
					dispatch({
						type: this.state.selectedAction,
						payload: {
							...this.state.additionalParams,
							...values,
							playlistId: this.state.selectedPlaylistId,
							resolve,
							reject,
						},
					});
				} else {
					reject();
					this.showAlert({ title: i18n.t('common.error'), msg: i18n.t('playlists.playlistNamesExists') });
				}
			} else {
				reject(new SubmissionError({ _error: i18n.t('common.noInternetConnection') }));
			}
		});
	}

	actionExists(actions) {
		return (_.intersection(this.props.actions, actions)).length > 0;
	}

	showAlert = ({ title, msg, callback }) => {
		Alert.alert(
			title,
			msg,
			[
				{
					text: i18n.t('common.ok'),
					onPress: callback ? callback() :
						() => {},
				},
			],
			{ cancelable: false },
		);
	}

	processSortOptions = (callback) => {
		if (this.props.playlist.sortOrder === PLAYLIST_SORT.CUSTOM &&
			_.findIndex(this.state.sortOptions, { value: PLAYLIST_SORT.CUSTOM }) === -1
		) {
			// If sort is 'custom' but there is NO custom option = add custom option
			this.setState({
				sortOptions: [...this.state.sortOptions, {
					label: i18n.t('common.custom'),
					value: PLAYLIST_SORT.CUSTOM,
					withIcon: 'information',
				}],
			}, callback);
		} else if (this.props.playlist.sortOrder !== PLAYLIST_SORT.CUSTOM &&
			_.findIndex(this.state.sortOptions, { value: PLAYLIST_SORT.CUSTOM }) >= 0
		) {
			// If sort is NOT 'custom' but there is custom option = remove custom option
			this.setState({
				sortOptions: _.filter(this.state.sortOptions, (option) => option.value !== PLAYLIST_SORT.CUSTOM),
			}, callback);
		} else if (_.isFunction(callback)) {
			callback();
		}
	}

	sortChange = (value) => {
		if (value === PLAYLIST_SORT.CUSTOM) {
			this.sortPicker.close(() => {
				this.sortCustomInfo.open();
			});
		} else if (value === this.props.playlist.sortOrder) {
			this.sortPicker.close();
		} else if (this.props.playlist.sortOrder === PLAYLIST_SORT.CUSTOM) {
			this.setState({ nextSortOption: value }, () => {
				this.sortPicker.close(() => {
					if (PLAYLIST_SORT.MOST_RECENTLY_ADDED === this.state.nextSortOption && this.sortChangeCustomToMostDialogue) {
						this.sortChangeCustomToMostDialogue.open();
					} else if (PLAYLIST_SORT.LEAST_RECENTLY_ADDED === this.state.nextSortOption
						&& this.sortChangeCustomToLeastDialogue) {
						this.sortChangeCustomToLeastDialogue.open();
					}
				});
			});
		} else {
			this.sortPicker.close(() => {
				this.changeSorting(value);
			});
		}
	}

	sortCustomInfoClose = () => {
		this.sortCustomInfo.close(() => {
			this.sortPicker.open();
		});
	}

	sortConfirmChangeCustom = () => {
		this.changeSorting(this.state.nextSortOption);
	}

	changeSorting = (sortOrder) => {
		if (this.props.isConnected) {
			this.props.changeSorting(
				this.state.selectedPlaylistId,
				sortOrder,
				() => {
					this.props.setReorderingPhotosStatus();
				},
				(err) => {
					this.props.toastError(err);
				},
			);
		} else {
			this.props.toastError({ text: i18n.t('common.noInternetConnection') });
		}
	}

	render() {
		const sortMostRecentSelected = this.props.playlist.sortOrder === PLAYLIST_SORT.MOST_RECENTLY_ADDED
			&& !this.props.contentSeqChanged;
		const sortLeastRecentSelected = this.props.playlist.sortOrder === PLAYLIST_SORT.LEAST_RECENTLY_ADDED
			&& !this.props.contentSeqChanged;
		const sortCustomSelected = this.props.playlist.sortOrder === PLAYLIST_SORT.CUSTOM || this.props.contentSeqChanged;

		return (
			<View>
				{this.actionExists([RENAME_PLAYLIST]) &&
				<ModalNameForm
					ref={(ref) => { this.modalNameForm = ref; }}
					form={`${this.props.route}NameForm`}
					onRequestClose={this.closeAction}
					onSubmit={this.submitActionForm}
					onSubmitSuccess={() => {
						this.closeAction(this.state.onActionSuccess);
					}}
					onSubmitFail={(errors) => {
						this.onSubmitFail(errors);
						this.modalNameForm.reset();
					}}
					onCancel={this.closeAction}
					formTitle={i18n.t('playlists.renamePlaylist')}
					placeholder={i18n.t('playlists.playlistName')}
					initialValues={{ name: this.state.selectedPlaylistName }}
					enableReinitialize
				/>}
				{this.actionExists([DELETE_PLAYLIST]) &&
				<Form
					form={`${this.props.route}DeleteForm`}
					onSubmit={this.submitActionForm}
					onSubmitSuccess={() => {
						this.closeAction(this.state.onActionSuccess);
					}}
					onSubmitFail={this.onSubmitFail}
				>
					<Dialogue
						ref={(ref) => { this.deleteDialogue = ref; }}
						loading={this.props.deleteFormMeta.submitting}
						withClose={false}
						onRequestClose={this.closeAction}
					>
						<Dialogue.Title>{i18n.t('playlists.deletePlaylist')}</Dialogue.Title>
						<Dialogue.Description>{i18n.t('playlists.deleteConfirmText', { playlistName: this.state.selectedPlaylistName })}</Dialogue.Description>
						<Dialogue.Action onPress={this.closeAction} testID="Cancel">{i18n.t('common.cancel')}</Dialogue.Action>
						<Dialogue.Action onPress={this.props.submitDeleteForm} color="red" testID="Delete">{i18n.t('common.delete')}</Dialogue.Action>
					</Dialogue>
				</Form>}
				{this.actionExists([DELETE_SHARED_PLAYLIST]) &&
				<Form
					form={`${this.props.route}DeleteForm`}
					onSubmit={this.submitActionForm}
					onSubmitSuccess={() => {
						this.closeAction(this.state.onActionSuccess);
					}}
					onSubmitFail={this.onSubmitFail}
				>
					<Dialogue
						ref={(ref) => { this.deleteSharedDialogue = ref; }}
						loading={this.props.deleteFormMeta.submitting}
						withClose={false}
						onRequestClose={this.closeAction}
					>
						<Dialogue.Title>{i18n.t('playlists.deletePlaylist')}</Dialogue.Title>
						<Dialogue.Description>{i18n.t('playlists.deleteSharedConfirmText', { playlistName: this.state.selectedPlaylistName })}</Dialogue.Description>
						<Dialogue.Action onPress={this.closeAction} testID="Cancel">{i18n.t('common.cancel')}</Dialogue.Action>
						<Dialogue.Action onPress={this.props.submitDeleteForm} color="red" testID="Delete">{i18n.t('common.delete')}</Dialogue.Action>
					</Dialogue>
				</Form>}
				{this.actionExists([LEAVE_SHARED_PLAYLIST]) &&
				<ModalForm
					ref={(ref) => { this.leaveSharedPlaylistDialogue = ref; }}
					form={`${this.props.route}DeleteContentForm`}
					onSubmit={this.submitActionForm}
					onSubmitSuccess={() => {
						this.closeAction(this.state.onActionSuccess);
					}}
					onSubmitFail={(errors) => {
						this.onSubmitFail(errors);
						this.leaveSharedPlaylistDialogue.reset();
					}}
					onCancel={this.closeAction}
					submitText={i18n.t('common.confirm')}
					submitColor="red"
				>
					<Dialogue.Title>{i18n.t('playlists.exitPlaylist')}</Dialogue.Title>
					<Dialogue.Description>{i18n.t('playlists.exitPlaylistDialogue', { playlistName: this.state.selectedPlaylistName })}</Dialogue.Description>
				</ModalForm>}
				{this.actionExists([REMOVE_PLAYLIST_CONTENT]) &&
				<ModalForm
					ref={(ref) => { this.removeContentDialogue = ref; }}
					form={`${this.props.route}DeleteContentForm`}
					onSubmit={this.submitActionForm}
					onSubmitSuccess={() => {
						this.closeAction(this.state.onActionSuccess);
					}}
					onSubmitFail={(errors) => {
						this.onSubmitFail(errors);
						this.removeContentDialogue.reset();
					}}
					onCancel={this.closeAction}
					submitText={i18n.t('common.remove')}
					submitColor="red"
				>
					{this.state.isShared ?
						<Dialogue.Title>{i18n.t('contents.removeContent')}</Dialogue.Title>
						:
						<Dialogue.Title>{i18n.t('contents.removeItems')}</Dialogue.Title>
					}
					{this.state.isShared ?
						<Dialogue.Description>{i18n.t('contents.removeSelectedSharedPlaylistItem')}</Dialogue.Description>
						:
						<Dialogue.Description>{i18n.t('contents.removeSelectedItemsConfirm')}</Dialogue.Description>
					}
				</ModalForm>}
				{this.actionExists([REMOVE_SHARED_PLAYLIST_CONTENT]) &&
				<ModalForm
					ref={(ref) => { this.removeSharedPlaylistContentDialouge = ref; }}
					form={`${this.props.route}DeleteContentForm`}
					onSubmit={this.submitActionForm}
					onSubmitSuccess={() => {
						this.closeAction(this.state.onActionSuccess);
					}}
					onSubmitFail={(errors) => {
						this.onSubmitFail(errors);
						this.removeSharedPlaylistContentDialouge.reset();
					}}
					onCancel={this.closeAction}
					submitText={i18n.t('common.confirm')}
					submitColor="red"
				>
					<Dialogue.Title>{i18n.t('contents.removeContent')}</Dialogue.Title>
					<Dialogue.Description>{i18n.t('contents.removeSelectedSharedPlaylistItem')}</Dialogue.Description>
				</ModalForm>}
				{this.actionExists([REMOVE_SHARED_PLAYLIST_AUDIENCE]) &&
				<ModalForm
					ref={(ref) => { this.removeAudienceDialouge = ref; }}
					form={`${this.props.route}DeleteContentForm`}
					onSubmit={this.submitActionForm}
					onSubmitSuccess={() => {
						this.closeAction(this.state.onActionSuccess);
					}}
					onSubmitFail={(errors) => {
						this.onSubmitFail(errors);
						this.removeAudienceDialouge.reset();
					}}
					onCancel={this.closeAction}
					submitText={i18n.t('common.confirm')}
					submitColor="red"
				>
					<Dialogue.Title>{i18n.t('contents.removeFriend')}</Dialogue.Title>
					{this.state.contributorsListLength === 1 ?
						<Dialogue.Description>
							{i18n.t('contents.unsharePlaylistFromYourOnlyFriend', { name: this.state.selectedContributor })}
							{'\n\n'}
							{i18n.t('contents.unsharePlaylistNotice')}
						</Dialogue.Description>
						:
						<Dialogue.Description>
							{
								i18n.t('contents.unsharePlaylistFromFriend', { name: this.state.selectedContributor })
							}
						</Dialogue.Description>
					}
				</ModalForm>}
				{this.actionExists([SET_PLAYLIST_SORT]) &&
				<View>
					<ActionSheet
						ref={(actionSheet) => { this.sortPicker = actionSheet; }}
					>
						<ActionSheet.Title>{i18n.t('common.arrangeBy')}</ActionSheet.Title>
						<ActionSheet.Action style={styles.sortActions} onPress={() => this.sortChange(PLAYLIST_SORT.MOST_RECENTLY_ADDED)} testID="SortMostRecentAdded">
							<Text textStyle={ActionSheet.Action.defaultProps.textStyle} color={sortMostRecentSelected ? 'blue' : ActionSheet.Action.defaultProps.color}>{i18n.t('common.mostRecentlyAdded')}</Text>
							{sortMostRecentSelected && <NixplayIcon name="check" color="blue" style={styles.sortActionCheckmark} />}
						</ActionSheet.Action>
						<ActionSheet.Action style={styles.sortActions} onPress={() => this.sortChange(PLAYLIST_SORT.LEAST_RECENTLY_ADDED)} testID="SortLeastRecentAdded">
							<Text textStyle={ActionSheet.Action.defaultProps.textStyle} color={sortLeastRecentSelected ? 'blue' : ActionSheet.Action.defaultProps.color}>{i18n.t('common.leastRecentlyAdded')}</Text>
							{sortLeastRecentSelected && <NixplayIcon name="check" color="blue" style={styles.sortActionCheckmark} />}
						</ActionSheet.Action>
						{sortCustomSelected &&
							<ActionSheet.Action style={styles.sortActions} onPress={() => this.sortPicker && this.sortPicker.close()} testID="SortCustom">
								<Text color="blue" textStyle={ActionSheet.Action.defaultProps.textStyle}>{i18n.t('common.custom')}</Text>
								<NixplayIcon name="check" color="blue" style={styles.sortActionCheckmark} />
							</ActionSheet.Action>}
						<ActionSheet.Cancel textStyle="body" color="blue" testID="Cancel" onPress={() => this.sortPicker && this.sortPicker.close()} >{i18n.t('common.cancel')}</ActionSheet.Cancel>
					</ActionSheet>
					<Dialogue
						ref={(ref) => { this.sortCustomInfo = ref; }}
						withClose={false}
						onRequestClose={this.sortCustomInfoClose}
					>
						<Dialogue.Additional style={{ marginTop: 0 }}>
							<Text style={{ marginBottom: 8 }} textStyle="subhead">{i18n.t('playlists.sortCustomInfoTitle')}</Text>
							<Text textStyle="footnote" color="textGrey">{i18n.t('playlists.sortCustomInfoBody')}</Text>
						</Dialogue.Additional>
						<Dialogue.Action
							onPress={this.sortCustomInfoClose}
							color="blue"
							testID="SortCustomInfoGotIt"
						>{i18n.t('common.gotIt')}
						</Dialogue.Action>
					</Dialogue>
					<Dialogue
						ref={(ref) => { this.sortChangeCustomToMostDialogue = ref; }}
						withClose={false}
						onRequestClose={() => this.sortChangeCustomToMostDialogue && this.sortChangeCustomToMostDialogue.close()}
					>
						<Dialogue.Title>{i18n.t('playlists.dialogue.sort.change.fromCustomToMost.title')}</Dialogue.Title>
						<Dialogue.Description align="left">{i18n.t('playlists.dialogue.sort.change.fromCustomToMost.description')}</Dialogue.Description>
						<Dialogue.Action onPress={() => this.sortChangeCustomToMostDialogue && this.sortChangeCustomToMostDialogue.close()} testID="Cancel">{i18n.t('common.cancel')}</Dialogue.Action>
						<Dialogue.Action
							onPress={() => {
								if (this.sortChangeCustomToMostDialogue) {
									this.sortChangeCustomToMostDialogue.close(this.sortConfirmChangeCustom);
								}
							}}
							color="blue"
							testID="SortChangeConfirm"
						>{i18n.t('common.ok')}
						</Dialogue.Action>
					</Dialogue>
					<Dialogue
						ref={(ref) => { this.sortChangeCustomToLeastDialogue = ref; }}
						withClose={false}
						onRequestClose={() => this.sortChangeCustomToLeastDialogue && this.sortChangeCustomToLeastDialogue.close()}
					>
						<Dialogue.Title>{i18n.t('playlists.dialogue.sort.change.fromCustomToLeast.title')}</Dialogue.Title>
						<Dialogue.Description align="left">{i18n.t('playlists.dialogue.sort.change.fromCustomToLeast.description')}</Dialogue.Description>
						<Dialogue.Action onPress={() => this.sortChangeCustomToLeastDialogue && this.sortChangeCustomToLeastDialogue.close()} testID="Cancel">{i18n.t('common.cancel')}</Dialogue.Action>
						<Dialogue.Action
							onPress={() => {
								if (this.sortChangeCustomToLeastDialogue) {
									this.sortChangeCustomToLeastDialogue.close(this.sortConfirmChangeCustom);
								}
							}}
							color="blue"
							testID="SortChangeConfirm"
						>{i18n.t('common.ok')}
						</Dialogue.Action>
					</Dialogue>
				</View>}
			</View>
		);
	}
}

const mapStateToProps = (state, ownProps) => {
	const { route } = ownProps;
	return {
		deleteFormMeta: {
			submitting: isSubmitting(`${route}DeleteForm`)(state),
		},
		isConnected: state.network.isConnected,
	};
};

const mapActionsToProps = (dispatch, ownProps) => {
	const { route } = ownProps;
	return {
		submitDeleteForm() {
			dispatch(submit(`${route}DeleteForm`));
		},
		changeSorting(playlistId, order, resolve, reject) {
			dispatch({
				type: SET_PLAYLIST_SORT,
				payload: {
					playlistId,
					order,
					resolve,
					reject,
				},
			});
		},
		setReorderingPhotosStatus() {
			dispatch({ type: START_REORDERING_PHOTOS_IN_PLAYLIST, payload: {} });
		},
		toastError(payload) {
			dispatch({ type: SHOW_TOAST_ERROR, payload });
		},
	};
};

export default connect(
	mapStateToProps,
	mapActionsToProps,
	null,
	{ forwardRef: true },
)(PlaylistActionsComponent);
