const MamiChannelInfo = function(name, hasPassword = false, isTemporary = true, isUserChannel = false) {
    if(typeof name !== 'string')
        throw 'name must be a string';
    if(typeof hasPassword !== 'boolean')
        throw 'hasPassword must be a boolean';
    if(typeof isTemporary !== 'boolean')
        throw 'isTemporary must be a boolean';
    if(typeof isUserChannel !== 'boolean')
        throw 'isUserChannel must be a boolean';

    return {
        get name() { return name; },
        set name(value) {
            if(typeof value !== 'string')
                throw 'value must be a string';
            name = value;
        },

        get hasPassword() { return hasPassword; },
        set hasPassword(value) {
            if(typeof value !== 'boolean')
                throw 'value must be a boolean';
            hasPassword = value;
        },

        get isTemporary() { return isTemporary; },
        set isTemporary(value) {
            if(typeof value !== 'boolean')
                throw 'value must be a boolean';
            isTemporary = value;
        },

        get isUserChannel() { return isUserChannel; },
    };
};

Umi.Channels = (function() {
    const chans = new Map;
    let currentName = null;

    const onAdd = [];
    const onRemove = [];
    const onClear = [];
    const onUpdate = [];
    const onSwitch = [];

    return {
        OnAdd: onAdd,
        OnRemove: onRemove,
        OnClear: onClear,
        OnUpdate: onUpdate,
        OnSwitch: onSwitch,
        Add: function(channel) {
            const channelName = channel.name;
            if(!chans.has(channelName)) {
                chans.set(channelName, channel);

                for(const i in onAdd)
                    onAdd[i](channel);
            }
        },
        Remove: function(channel) {
            const channelName = channel.name;
            if(chans.has(channelName)) {
                chans.delete(channelName);

                for(const i in onRemove)
                    onRemove[i](channel);
            }
        },
        Clear: function() {
            chans.clear();

            for(const i in onClear)
                onClear[i]();
        },
        All: function() {
            return Array.from(chans.values());
        },
        Get: function(channelName) {
            channelName = channelName.toString();
            if(chans.has(channelName))
                return chans.get(channelName);
            return null;
        },
        Update: function(channelName, channel) {
            channelName = channelName.toString();
            chans.set(channelName, channel);

            for(const i in onUpdate)
                onUpdate[i](name, channel);
        },
        Current: function() {
            return currentName;
        },
        Switch: function(channelName) {
            const old = currentName;
            currentName = channelName;

            for(const i in onSwitch)
                onSwitch[i](old, channelName);
        },
    };
})();
