"use strict";

const flattenChannels = (channels, name) => {
    if (Array.isArray(channels))
        return channels.join(',');
    else if (typeof channels === 'string')
        return channels;
    else if (!channels)
        return '';
    else
        throw TypeError(`${name} must be a string or an array of strings`);
}

const assertNonEmptyString = (value, name) => {
    if (typeof value !== 'string')
        throw TypeError(`${name} must be a string`);
    else if (!value)
        throw TypeError(`${name} cannot be empty`);
}

export class UrlFactory
{
    constructor(baseUrl, group, channels = {}) {
        assertNonEmptyString(group, 'group');
        const base = new URL(baseUrl || '.', location.href);
        if (!base.pathname.endsWith('/')) {
            base.pathname += '/';
        }
        this.generateBaseUrls(base, group, channels);
    }

    /**
     * 
     * @param {URL} base 
     * @param {string} group 
     * @param {string[]|string} param2.pub
     * @param {string[]|string} param2.sub
     */
    generateBaseUrls(base, group, { pub, sub }) {
        pub = flattenChannels(pub);
        sub = flattenChannels(sub);
        this.restBase = base.href + 'rest/';
        this.pubBase = base.href + group + '/pub/';
        base.protocol = 'ws' + base.protocol.substring(4);
        this.msgBase = base.href + group + `/room/pub${pub}/sub${sub}/`;
    }

    /**
     * Returns the base URL for the messenger REST service
     * 
     * @returns {string}
     */
    restEndpoint(path) {
        return this.restBase + path;
    }

    /**
     * Returns the publisher endpoint for the given channels
     * 
     * @param {string|string[]} channels 
     * @returns {string}
     */
    publisherEndpoint(channels) {
        channels = flattenChannels(channels, 'channels');
        if (!channels) throw TypeError('at least one channel must be provided');
        return this.pubBase + channels;
    }

    /**
     * Returns the messenger endpoint to the given token
     * @param {string} token
     * @returns {string}
     */
    messengerEndpoint(token = '') {
        return this.msgBase + token;
    }
}

export class ControllerUrlFactory extends UrlFactory
{
    generateBaseUrls(base, group, { sub }) {
        sub = flattenChannels(sub);
        this.restBase = base.href + 'rest/';
        this.pubBase = base.href + group + '/pub/';
        base.protocol = 'ws' + base.protocol.substring(4);
        this.msgBase = base.href + group + `/controller/sub${sub}/`;
    }
}
