const cache = {};

export function getComponentFromGist ( id ) {
	let cancelled = false;

	if ( !cache[ id ] ) {
		cache[ id ] = new Promise( ( resolve, reject ) => {
			const request = new XMLHttpRequest();
			request.open( 'GET', `https://api.github.com/gists/${id}` );
			request.onload = () => resolve( request );
			request.onerror = () => reject( new TypeError('Network request failed') );
			request.send();
		} )
			.then( r => JSON.parse(r.responseText) )
			.then( gist => {
				const components = [];

				const componentFiles = Object.keys( gist.files ).filter( file => /\.html$/.test( file ) );

				if ( componentFiles.length === 1 && componentFiles[0] === 'component.html' ) {
					// legacy
					components.push({
						name: 'App',
						source: gist.files[ 'component.html' ].content
					});
				} else {
					componentFiles.forEach( file => {
						const name = file.slice( 0, -5 );
						const source = gist.files[ file ].content;

						components.push({ name, source });
					});
				}

				const jsonFile = gist.files[ 'data.json' ];
				const json = jsonFile && jsonFile.content || '{}';

				return { components, json };
			})
			.catch( err => {
				cache[ id ] = null;
				throw err;
			});
	}

	const promise = cache[ id ].then( component => {
		if ( cancelled ) throw new Error( `Request was cancelled` );
		return component;
	});

	promise.cancel = () => {
		cancelled = true;
	};

	return promise;
}

export function saveComponentAsGist ( components, json ) {
	const files = {
		'README.md': {
			content: `# Svelte component\n\nThis gist was generated by the [Svelte REPL](https://svelte.technology/repl). Visit https://svelte.technology/repl?gist=this_gist_id to see it.`
		},

		'data.json': {
			content: json
		}
	};

	components.forEach( component => {
		files[ `${component.name}.html` ] = {
			content: component.source
		};
	});

	const body = JSON.stringify({
		description: 'Svelte component',
		public: true,
		files
	});

	return new Promise( ( resolve, reject ) => {
		const request = new XMLHttpRequest();
		request.open( 'POST', `https://api.github.com/gists` );
		request.onload = () => resolve( request );
		request.onerror = () => reject( new TypeError('Network request failed') );
		request.send(body);
	} )
		.then( r => JSON.parse(r.responseText) )
		.then( gist => gist.id );
}

const cache = {};

export function getComponentFromGist ( id ) {
	let cancelled = false;

	if ( !cache[ id ] ) {
		cache[ id ] = new Promise( ( resolve, reject ) => {
			const request = new XMLHttpRequest();
			request.open( 'GET', `https://api.github.com/gists/${id}` );
			request.onload = () => resolve( request );
			request.onerror = () => reject( new TypeError('Network request failed') );
			request.send();
		} )
			.then( r => JSON.parse(r.responseText) )
			.then( gist => {
				const components = [];

				const componentFiles = Object.keys( gist.files ).filter( file => /\.html$/.test( file ) );

				if ( componentFiles.length === 1 && componentFiles[0] === 'component.html' ) {
					// legacy
					components.push({
						name: 'App',
						entry: true,
						source: gist.files[ 'component.html' ].content
					});
				} else {
					componentFiles.forEach( file => {
						const name = file.slice( 0, -5 );
						const source = gist.files[ file ].content;

						components.push({ name, entry: name === 'App', source });
					});
				}

				const jsonFile = gist.files[ 'data.json' ];
				const json = jsonFile && jsonFile.content || '{}';

				return { components, json };
			})
			.catch( err => {
				cache[ id ] = null;
				throw err;
			});
	}

	const promise = cache[ id ].then( component => {
		if ( cancelled ) throw new Error( `Request was cancelled` );
		return component;
	});

	promise.cancel = () => {
		cancelled = true;
	};

	return promise;
}

export function saveComponentAsGist ( components, json ) {
	const files = {
		'README.md': {
			content: `# Svelte component\n\nThis gist was generated by the [Svelte REPL](https://svelte.technology/repl). Visit https://svelte.technology/repl?gist=this_gist_id to see it.`
		},

		'data.json': {
			content: json
		}
	};

	components.forEach( component => {
		files[ `${component.name}.html` ] = {
			content: component.source
		};
	});

	const body = JSON.stringify({
		description: 'Svelte component',
		public: true,
		files
	});

	return new Promise( ( resolve, reject ) => {
		const request = new XMLHttpRequest();
		request.open( 'POST', `https://api.github.com/gists` );
		request.onload = () => resolve( request );
		request.onerror = () => reject( new TypeError('Network request failed') );
		request.send(body);
	} )
		.then( r => JSON.parse(r.responseText) )
		.then( gist => gist.id );
}

mark App.html as the entry component when loading from a gist