import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import magnet from 'magnet-uri';
import WebTorrent from 'webtorrent';
import * as requestActions from '../../redux/requestActions';
import { saveAs } from 'file-saver/FileSaver';
import { client } from './index';

const DEFAULT_PICTURE = 'resources/images/avatar-empty.jpeg';

class FileEntry extends Component
{
	state = {
		active   : false,
		numPeers : 0,
		progress : 0,
		files    : null
	};

	saveFile = (file) =>
	{
		file.getBlob((err, blob) =>
		{
			if (err)
			{
				return this.props.notify({
					text : 'An error occurred while saving a file'
				});
			}
	
			saveAs(blob, file.name);
		});
	};

	handleTorrent = (torrent) =>
	{
		// Torrent already done, this can happen if the
		// same file was sent multiple times.
		if (torrent.progress === 1)
		{
			this.setState({
				files    : torrent.files,
				numPeers : torrent.numPeers,
				progress : 1,
				active   : false,
				timeout  : false
			});

			return;
		}

		const onProgress = () =>
		{
			this.setState({
				numPeers : torrent.numPeers,
				progress : torrent.progress
			});
		};

		onProgress();

		setInterval(onProgress, 500);

		torrent.on('done', () => 
		{
			onProgress();
			clearInterval(onProgress);

			this.setState({
				files  : torrent.files,
				active : false
			});
		});
	};

	handleDownload = () =>
	{
		this.setState({
			active : true
		});
		
		const magnetURI = this.props.data.file.magnet;

		const existingTorrent = client.get(magnetURI);

		if (existingTorrent)
		{
			// Never add duplicate torrents, use the existing one instead.
			return this.handleTorrent(existingTorrent);
		}

		client.add(magnetURI, this.handleTorrent);

		setTimeout(() =>
		{
			if (this.state.active && this.state.numPeers === 0)
			{
				this.setState({
					timeout : true
				});
			}
		}, 10 * 1000);
	}

	render()
	{
		return (
			<div className='file-entry'>
				<img className='file-avatar' src={this.props.data.picture || DEFAULT_PICTURE} />
	
				<div className='file-content'>
					<Choose>
						<When condition={this.props.data.me}>
							<p>You shared a file.</p>
						</When>
						<Otherwise>
							<p>{this.props.data.name} shared a file.</p>
						</Otherwise>
					</Choose>

					<If condition={!this.state.active && !this.state.files}>
						<div className='file-info'>
							<Choose>
								<When condition={WebTorrent.WEBRTC_SUPPORT}>
									<span className='button' onClick={this.handleDownload}>
										<img src='resources/images/download-icon.svg' />
									</span>
								</When>
								<Otherwise>
									<p>
										Your browser does not support downloading files using WebTorrent.
									</p>
								</Otherwise>
							</Choose>
							<p>{magnet.decode(this.props.data.file.magnet).dn}</p>
						</div>
					</If>

					<If condition={this.state.active && this.state.numPeers === 0}>
						<Fragment>
							<p>
								Locating peers
							</p>

							{this.state.timeout && (
								<p>
									If this process takes a long time, there might not be anyone seeding
									this torrent. Try asking someone to reupload the file that you want.
								</p>
							)}
						</Fragment>
					</If>

					<If condition={this.state.active && this.state.numPeers > 0}>
						<progress value={this.state.progress} />
					</If>

					<If condition={this.state.files}>
						<Fragment>
							<p>Torrent finished downloading.</p>

							{this.state.files.map((file, i) => (
								<div className='file-info' key={i}>
									<span className='button' onClick={() => this.saveFile(file)}>
										<img src='resources/images/save-icon.svg' />
									</span>

									<p>{file.name}</p>
								</div>
							))}
						</Fragment>
					</If>
				</div>
			</div>
		);
	}
}

export const FileEntryProps = {
	data : PropTypes.shape({
		name    : PropTypes.string.isRequired,
		picture : PropTypes.string,
		file    : PropTypes.shape({
			magnet : PropTypes.string.isRequired
		}).isRequired,
		me : PropTypes.bool
	}).isRequired,
	notify : PropTypes.func.isRequired
};

FileEntry.propTypes = FileEntryProps;

const mapDispatchToProps = {
	notify : requestActions.notify
};

export default connect(
	undefined,
	mapDispatchToProps
)(FileEntry);