import { Downloader } from "./downloader";
import { Links } from "./links";

let links = new Links;

function sleep(ms: number) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

export class UrlPool {

	urls: string[];
	used: boolean[] = [];
	generating = false;
	downloader?: Downloader;

	constructor(urls?: string[]) {
		this.urls = urls ? urls : [];
		for(let i=0; i<this.urls.length; i++) {
			this.used[i] = false;
		}
	}

	get_raw(): [number, string] | undefined {
		for(let i=0; i<this.urls.length; i++) {
			if(this.used[i]) continue;
			this.used[i] = true;
			return [i, this.urls[i]];
		}
	}

	async get(): Promise<[number, string] | undefined> {
		let url = this.get_raw();
		if(url) return url;
		return new Promise((complete) => {
			let check = setInterval(() => {
				let url = this.get_raw();
				if(url) {
					clearInterval(check);
					complete(url);
				}
			}, 100);
		});
	}

	return(i: number) {
		this.used[i] = false;
	}

	add(url: string) {
		this.urls.push(url);
		this.used.push(false);
	}

	available(count?: number) {
		let available: number[] = [];
		for(let i=0; i<this.used.length; i++) {
			if(!this.used[i]) {
				available.push(i);
			}
		}
		return count ? available.slice(0, count) : available;
	}

	async generate(id: string) {
		this.generating = true;
		while(this.urls.length < 10) {
		
			let link = await links.link(id);
			if(link) this.add(link);
			console.log(link);
			await sleep(2000);

		}
		this.generating = false;
	}

	get_downloader() {
		if(this.downloader) return this.downloader;
		this.downloader = new Downloader(this)
		return this.downloader;
	}

}

export class UrlPoolStorage {

	pools: {[U: string]: UrlPool} = {};

	get(id: string) {
		return this.pools[id] ? this.pools[id] : this.new(id);
	}

	new(id: string) {
		let pool = new UrlPool;
		pool.generate(id);
		this.pools[id] = pool;
		return pool;
	}

}