const MamiEventTargetScoped = function(eventTarget, prefix) {
    if(typeof eventTarget !== 'object' || eventTarget === null)
        throw 'eventTarget must be a non-null object';
    if(typeof prefix !== 'string')
        throw 'prefix must be a string';

    if(!prefix.endsWith(':'))
        prefix = prefix + ':';

    return {
        scopeTo: name => eventTarget.scopeTo(prefix + name),
        create: (name, ...args) => eventTarget.create(prefix + name, ...args),
        watch: (name, ...args) => eventTarget.watch(prefix + name, ...args),
        unwatch: (name, ...args) => eventTarget.unwatch(prefix + name, ...args),
        dispatch: (nameOrEvent, ...args) => eventTarget.dispatch(nameOrEvent instanceof Event ? nameOrEvent : (prefix + nameOrEvent), ...args),
    };
};

const MamiEventTargetWindow = function() {
    const createEvent = (name, detail) => new CustomEvent( name, (typeof detail === 'object' && detail !== null && 'detail' in detail ? detail : { detail: detail }));

    const public = {
        scopeTo: name => new MamiEventTargetScoped(public, name),
        create: createEvent,
        watch: (...args) => { window.addEventListener(...args); },
        unwatch: (...args) => { window.removeEventListener(...args); },
        dispatch: (nameOrEvent, ...args) => { window.dispatchEvent(nameOrEvent instanceof Event ? nameOrEvent : createEvent(nameOrEvent, ...args)); },
    };

    return public;
};
