const ArgumentType = require('./base');

/**
 * A type for command arguments that handles multiple other types
 * @extends {ArgumentType}
 */
class ArgumentUnionType extends ArgumentType {
	constructor(client, id) {
		super(client, id);

		/**
		 * Types to handle, in order of priority
		 * @type {ArgumentType[]}
		 */
		this.types = [];
		const typeIDs = id.split('|');
		for(const typeID of typeIDs) {
			const type = client.registry.types.get(typeID);
			if(!type) throw new Error(`Argument type "${typeID}" is not registered.`);
			this.types.push(type);
		}
	}

	async validate(val, msg, arg) {
		let results = this.types.map(type => !type.isEmpty(val, msg, arg) ? type.validate(val, msg, arg) : false);
		results = await Promise.all(results);
		if(results.some(valid => valid && typeof valid !== 'string')) return true;
		const errors = results.filter(valid => typeof valid === 'string');
		if(errors.length > 0) return errors.join('\n');
		return false;
	}

	async parse(val, msg, arg) {
		let results = this.types.map(type => !type.isEmpty(val, msg, arg) ? type.validate(val, msg, arg) : false);
		results = await Promise.all(results);
		for(let i = 0; i < results.length; i++) {
			if(results[i] && typeof results[i] !== 'string') return this.types[i].parse(val, msg, arg);
		}
		throw new Error(`Couldn't parse value "${val}" with union type ${this.id}.`);
	}

	isEmpty(val, msg, arg) {
		return !this.types.some(type => !type.isEmpty(val, msg, arg));
	}
}

module.exports = ArgumentUnionType;

@@ -655,33 +655,34 @@
 (val, msg, arg) 
-?
+&&
  type.validate(v
@@ -690,32 +690,24 @@
 l, msg, arg)
- : false
 );%0A%09%09results
@@ -1055,9 +1055,10 @@
 rg) 
-?
+&&
  typ
@@ -1086,16 +1086,8 @@
 arg)
- : false
 );%0A%09

Simplify validation checks in ArgumentUnionType