"use strict";
const defaultOptions = require("./defaultOptions");
const each = require("promise-each");
const list2Array = require("list-to-array");
const parseMetaRefresh = require("http-equiv-refresh");
const parseSrcset = require("parse-srcset");



function plugin(options)
{
	options = Object.assign({}, defaultOptions, options);

	if (typeof options.eachURL !== "function") 
	{
		throw new Error("eachURL must be a function");
	}

	return function PostHTML_URLs(tree)
	{
		const promises = [];

		tree.walk( function(node)
		{
			if (node.attrs == null) return node;
			
			const tagGroup = options.filter[node.tag];

			if (tagGroup === undefined) return node;
			
			Object.keys(node.attrs).forEach( function(attrName)
			{
				if (tagGroup[attrName] === undefined) return;

				if (typeof tagGroup[attrName] === "function")
				{
					if (tagGroup[attrName](node, attrName) === false) return;
				}

				switch (attrName)
				{
					case "content":
					{
						promises.push( transformMetaRefresh(node, attrName, options.eachURL) );
						break;
					}
					case "ping":
					{
						promises.push( transformCommaSeparated(node, attrName, options.eachURL) );
						break;
					}
					case "srcset":
					{
						promises.push( transformSrcset(node, attrName, options.eachURL) );
						break;
					}
					default:
					{
						promises.push( transformDefault(node, attrName, options.eachURL) );
					}
				}
			});

			return node;
		});

		return Promise.all(promises).then(() => tree);
	};
}



function transformCommaSeparated(node, attrName, transformer)
{
	const values = list2Array( node.attrs[attrName], "," );

	if (values.length === 0) return;

	const promises = [];

	values.forEach( function(value)
	{
		const promise = Promise.resolve( transformer(value, attrName, node.tag) );
		promises.push(promise);
	});

	return Promise.all(promises)
	.then(newValues => node.attrs[attrName] = newValues.join(", "));
}



function transformDefault(node, attrName, transformer)
{
	return Promise.resolve( transformer( node.attrs[attrName], attrName, node.tag ) )
	.then(newValue => node.attrs[attrName] = newValue);
}



function transformMetaRefresh(node, attrName, transformer)
{
	const value = parseMetaRefresh( node.attrs[attrName] );

	if (value.length === 0) return;
	
	return Promise.resolve( transformer(value.url, attrName, node.tag) )
	.then(newValue => node.attrs[attrName] = `${value.timeout}; url=${newValue}`);
}



function transformSrcset(node, attrName, transformer)
{
	const values = parseSrcset( node.attrs[attrName] );

	if (values.length === 0) return;

	const promises = [];

	values.forEach( function(value)
	{
		const promise = Promise.resolve( transformer(value.url, attrName, node.tag) )
		.then( function(newValue)
		{
			const d = value.d !== undefined ? ` ${value.d}x` : "";
			const h = value.h !== undefined ? ` ${value.h}h` : "";
			const w = value.w !== undefined ? ` ${value.w}w` : "";

			return `${newValue}${w}${h}${d}`;
		});

		promises.push(promise);
	});

	return Promise.all(promises)
	.then(newValues => node.attrs[attrName] = newValues.join(", "));
}



module.exports = plugin;