import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Moment from 'moment';
import { createClient } from 'contentful';
import { createClient as createWriteClient } from 'contentful-management';
import {
	Accordion as SemanticAccordion,
	Button as SemanticButton,
	Dropdown as SemanticDropdown,
	Icon as SemanticIcon,
	Image as SemanticImage,
	Input as SemanticInput,
	List as SemanticList,
	Modal as SemanticModal,
	Tab as SemanticTab
} from 'semantic-ui-react';
import Container from '../Container';
import Loader from '../Loader';
import Marked from '../Marked';

import * as styles from './Style.less';

export default class SidebarSupport extends Component {
	static propTypes = {
		visible: PropTypes.bool
	};

	static defaultProps = {
		visible: false
	};

	static openImage(href) {
		this.setState({
			modal: (
				<SemanticModal
					open
					basic
					onClose={() => {
						this.setState({ modal: null });
					}}
					className={styles.Modal}
				>
					<SemanticModal.Content>
						<SemanticImage
							src={href}
							className={styles.ModalImage}
						/>
					</SemanticModal.Content>
				</SemanticModal>
			)
		});
	}

	constructor(props) {
		super(props);

		SidebarSupport.openImage = SidebarSupport.openImage.bind(this);

		window.PP_Sidebar_OpenImage = SidebarSupport.openImage;

		this.state = {
			index: 0,
			fetchedEntries: false,
			ticket: false,
			categories: [],
			article: null,
			search: {
				active: false,
				value: '',
				results: []
			},
			voted: false,
			release: localStorage.getItem('docs-release') || null,
			releases: {},
			modal: null
		};

		if (global.test) {
			// Internal users get Preview API
			this.Contentful = createClient({
				space: 'mg298b52kz6q',
				accessToken: '682342e53a26811c1af151d4d33e8b3549d3a5986e84326c5d6781bb25a2ed12',
				host: 'preview.contentful.com'
			});
		} else {
			// External users get Published API
			this.Contentful = createClient({
				space: 'mg298b52kz6q',
				accessToken: '4b23e7321009c7aff939e9043ca2322b01534fa7bde040270146abfd26dc4bc3'
			});
		}

		this.ContentfulWrite = createWriteClient({
			accessToken: 'CFPAT-603ef95ac0ef08f0794dbe3216cf74ed6f0d84c70aa8bcab2bc0f1e4d5e0e53f'
		});
	}

	componentWillReceiveProps(nextProps) {
		if (nextProps.visible && !this.state.fetchedEntries) {
			this.fetchEntries();
		}
	}

	// Help

	static onChat() {
		if (
			hubspot
			&& hubspot.messages
			&& hubspot.messages.EXPERIMENTAL_API
			&& hubspot.messages.EXPERIMENTAL_API.requestWidgetOpen
		) {
			hubspot.messages.EXPERIMENTAL_API.requestWidgetOpen();
		} else {
			document.querySelector('#hubspot-messages-iframe-container iframe').contentWindow.postMessage(JSON.stringify({ type: 'request-open' }), 'https://app.hubspot.com');
		}
	}

	onTicket() {
		if (
			hbspt
			&& hbspt.forms
			&& hbspt.forms.create
		) {
			this.setState({
				ticket: true
			}, () => {
				hbspt.forms.create({
					portalId: '4470349',
					formId: '947519e8-f04f-4cc0-b0d1-3cb0da9a307e',
					target: '#Support',
					css: '',
					cssRequired: ''
				});
			});
		}
	}

	// Knowledge Base

	onSearch(term) {
		if (!term || term.length < 2) {
			this.setState(prevState => ({
				search: {
					...prevState.search,
					active: false,
					results: []
				}
			}));
		} else {
			this.Contentful.getEntries({
				content_type: 'knowledgeBase',
				query: term,
				select: 'fields.title,fields.category',
				limit: 10,
				order: '-fields.votes'
			})
				.then((articles) => {
					this.setState(prevState => ({
						search: {
							...prevState.search,
							active: true,
							results: articles.items
						}
					}));
				});
		}
	}

	openArticle(id) {
		this.Contentful.getEntries({
			content_type: 'knowledgeBase',
			'sys.id': id,
			select: 'fields.title,fields.content,fields.category,fields.votes',
			limit: 1
		})
			.then((response) => {
				this.setState({
					article: response.items[0],
					voted: false
				});
			});
	}

	vote(value) {
		this.ContentfulWrite.getSpace('mg298b52kz6q')
			// .then(space => space.getEnvironment('<environment-id>'))
			// .then(environment => environment.getEntry('<entry-id>'))
			.then(space => space.getEntry(this.state.article.sys.id))
			.then((entry) => {
				if (value === true) {
					entry.fields.votes['en-US'] += 1;
				} else {
					// Don't log "unhelpful" votes for now // TODO: Implement later
				}

				return entry.update();
			})
			.then(() => this.setState({
				voted: true
			}));
	}

	// Release Notes

	openRelease(release) {
		this.setState({
			release,
			index: 2
		}, () => {
			localStorage.setItem('docs-release', release);
		});
	}

	fetchEntries() {
		this.setState({ fetchedEntries: true });

		this.Contentful.getEntries({
			content_type: 'knowledgeBaseCategory',
			select: 'fields.title',
			order: 'fields.title'
		})
			.then((response) => {
				const categories = {};

				response.items.forEach((row) => {
					categories[row.sys.id] = { ...row.fields, id: row.sys.id, articles: [] };
				});

				this.Contentful.getEntries({
					content_type: 'knowledgeBase',
					select: 'fields.title,fields.category'
				})
					.then((articles) => {
						articles.items.forEach((row) => {
							if (row.fields.category) {
								categories[row.fields.category.sys.id].articles.push({ title: row.fields.title, id: row.sys.id });
							}
						});

						const accordian = [];

						Object.keys(categories).forEach((key) => {
							const category = categories[key];

							if (category.articles.length) {
								accordian.push({
									key: category.id,
									title: category.title,
									content: {
										content: (
											<SemanticList>
												{
													category.articles.map(row => (
														<SemanticList.Item
															key={row.id}
															onClick={() => this.openArticle(row.id)}
														>
															{row.title}
														</SemanticList.Item>
													))
												}
											</SemanticList>
										)
									}
								});
							}
						});

						this.setState({
							categories: accordian
						});
					});
			});

		this.Contentful.getEntries({
			content_type: 'release',
			'fields.channel': 'stable',
			select: 'fields.commitHash,fields.date,fields.channel,fields.notes',
			order: '-fields.date'
		})
			.then((response) => {
				const releases = {};

				response.items.forEach((row) => {
					releases[row.fields.commitHash] = { ...row.fields, id: row.sys.id };
				});

				this.setState(prevState => ({
					release: prevState.release ? prevState.release : response.items[0].fields.commitHash,
					releases
				}));
			});
	}

	render() {
		const {
			categories,
			article,
			releases
		} = this.state;

		const release = releases[this.state.release];

		return (
			<div
				className={styles.SidebarSupport}
			>
				<SemanticTab
					renderActiveOnly={false}
					activeIndex={this.state.index}
					menu={{
						secondary: true,
						pointing: true,
						attached: false
					}}
					onTabChange={(e, data) => {
						this.setState({
							index: data.activeIndex
						});
					}}
					panes={[
						{
							menuItem: 'Need Help?',
							pane: (
								<SemanticTab.Pane
									key="Help"
									className={styles.Help}
								>
									<Container className={styles.SupportOptions}>
										{
											this.state.ticket ? (
												<>
													<SemanticButton
														onClick={() => this.setState({ ticket: false })}
														className={styles.Back}
													>
														<SemanticIcon name="left arrow" />
														Back
													</SemanticButton>

													<div id="Support" />
												</>
											) : (
												<SemanticList>
													<SemanticList.Item
														onClick={() => SidebarSupport.onChat()}
													>
														<SemanticList.Icon className="comment dots alternate" />
														<SemanticList.Content>
															Chat with support
														</SemanticList.Content>
													</SemanticList.Item>
													<SemanticList.Item
														onClick={() => this.onTicket()}
													>
														<SemanticList.Icon className="bug" />
														<SemanticList.Content>
															Report a problem
														</SemanticList.Content>
													</SemanticList.Item>
													<SemanticList.Item>
														<SemanticList.Icon className="phone" />
														<SemanticList.Content>
															<span>
																For emergencies, call us at
															</span>

															<a href="tel:+17372103627">+1 (737) 210-3627</a>
														</SemanticList.Content>
													</SemanticList.Item>
												</SemanticList>
											)
										}
									</Container>
								</SemanticTab.Pane>
							)
						},
						{
							menuItem: 'FAQs',
							pane: (
								<SemanticTab.Pane
									key="KnowledgeBase"
									className={styles.KnowledgeBase}
								>
									{
										categories.length ? article ? (
											<Container className={styles.Article}>
												<SemanticButton
													onClick={() => this.setState({ article: null })}
													className={styles.Back}
												>
													<SemanticIcon name="left arrow" />
													Back
												</SemanticButton>

												<div className={styles.Markdown}>
													<h3>
														{article.fields.title}
													</h3>

													{Marked.display(article.fields.content)}
												</div>

												{
													!this.state.voted && (
														<div className={styles.Vote}>
															<p>
																Did you find this helpful?
															</p>

															<SemanticButton.Group>
																<SemanticButton
																	positive
																	onClick={() => this.vote(true)}
																>
																	Yes
																</SemanticButton>
																<SemanticButton
																	negative
																	onClick={() => this.vote(false)}
																>
																	No
																</SemanticButton>
															</SemanticButton.Group>
														</div>
													)
												}
											</Container>
										) : (
											<>
												<SemanticInput
													fluid
													className={styles.Search}
													placeholder="Search..."
													value={this.state.search.value}
													onChange={(e, { value }) => {
														this.setState(prevState => ({
															search: {
																...prevState.search,
																value
															}
														}));
													}}
													onKeyUp={(e) => {
														if (e.keyCode === 13 || e.key === 'Enter') {
															this.onSearch(this.state.search.value);
														}
													}}
													action={{
														icon: this.state.search.active ? 'times' : 'search',
														onClick: () => {
															if (this.state.search.active) {
																this.setState({
																	search: {
																		value: '',
																		active: false,
																		results: []
																	}
																});
															} else {
																this.onSearch(this.state.search.value);
															}
														}
													}}
												/>
												{
													this.state.search.active ? (
														<>
															{
																this.state.search.results.length > 0 ? (
																	<Container className={styles.SearchResults}>
																		<h5 className={styles.Heading}>
																			Search Results
																		</h5>

																		<SemanticList>
																			{
																				this.state.search.results.map(row => (
																					<SemanticList.Item
																						key={row.sys.id}
																						onClick={() => this.openArticle(row.sys.id)}
																					>
																						{row.fields.title}
																					</SemanticList.Item>
																				))
																			}
																		</SemanticList>
																	</Container>
																) : (
																	<div className={styles.SearchEmpty}>
																		<h5 className={styles.Heading}>
																			Search Results
																		</h5>

																		<p>
																			No results found
																		</p>
																	</div>
																)
															}
														</>
													) : (
														<Container className={styles.Articles}>
															{
																categories.length && (
																	<SemanticAccordion
																		fluid
																		defaultActiveIndex={0}
																		panels={categories}
																	/>
																)
															}
														</Container>
													)
												}
											</>
										) : (
											<Loader minimal />
										)
									}
								</SemanticTab.Pane>
							)
						},
						{
							menuItem: 'What\'s New',
							pane: (
								<SemanticTab.Pane
									key="Releases"
									className={styles.Releases}
								>
									{
										(release && releases) ? (
											<Container className={styles.Release}>
												<SemanticDropdown
													ref={(element) => { this.dropdownReleases = element; }}
													scrolling
													pointing="top left"
													search
													selectOnNavigation={false}
													selectOnBlur={false}
													options={Object.keys(releases).map(r => ({
														text: `${Moment(releases[r].date, 'YYYY-MM-DD HH:mm:ss ZZ').format('MMMM Do, YYYY')} (${releases[r].commitHash})`,
														value: releases[r].commitHash
													}))}
													value={release.commitHash}
													onChange={(e, { value }) => {
														this.openRelease(value);

														// override SUIs stupid selection logic
														const index = Object.keys(releases).findIndex(r => releases[r].commitHash === value) || 0;
														this.dropdownReleases.setState({ selectedIndex: index });
													}}
												/>
												{
													release.notes && (
														Marked.display(release.notes)
													)
												}
											</Container>
										) : (
											<Loader minimal />
										)
									}
								</SemanticTab.Pane>
							)
						}
					]}
				/>
				{this.state.modal}
			</div>
		);
	}
}
