const MamiTextTrigger = function(info) {
    const type = info.type,
        match = info.match;

    for(const i in match) {
        match[i] = match[i].split(';');
        for(const j in match[i])
            match[i][j] = match[i][j].trim().split(':');
    }

    const pub = {
        getType: function() { return type; },
        isSoundType: function() { return type === 'sound'; },
        isAliasType: function() { return type === 'alias'; },
        isMatch: function(matchText) {
            for(const i in match) {
                const out = (function(filters, text) {
                    let result = false;

                    for(const j in filters) {
                        const filter = filters[j];
                        switch(filter[0]) {
                            case 'lc':
                                text = text.toLowerCase();
                                break;

                            case 'is':
                                if(text === filter.slice(1).join(':'))
                                    result = true;
                                break;

                            case 'starts':
                                if(text.indexOf(filter.slice(1).join(':')) === 0)
                                    result = true;
                                break;

                            case 'has':
                                if(text.includes(filter.slice(1).join(':')))
                                    result = true;
                                break;

                            case 'hasnot':
                                if(text.includes(filter.slice(1).join(':')))
                                    result = false;
                                break;

                            default:
                                console.error('Unknown filter encountered: ' + filter.join(':'));
                                break;
                        }
                    }

                    return result;
                })(match[i], matchText);

                if(out) return true;
            }

            return false;
        },
    };

    if(type === 'sound') {
        const volume = info.volume || 1.0,
            rate = info.rate || 1.0,
            names = info.sounds || [];

        pub.getVolume = function() { return volume; };
        pub.getRate = function() {
            if(rate === 'rng')
                return 1.8 - (Math.random() * 1.5);
            return rate;
        };
        pub.getSoundNames = function() { return names; };
        pub.getRandomSoundName = function() { return names[Math.floor(Math.random() * names.length)]; };
    } else if(type === 'alias') {
        const aliasFor = info.for || [];

        pub.getFor = function() { return aliasFor; };
    } else
        throw 'Unsupported trigger type.';

    return pub;
};

const MamiTextTriggers = function() {
    let triggers = [];

    const addTrigger = function(triggerInfo) {
        if(triggerInfo === null || typeof triggerInfo.type !== 'string')
            throw 'triggerInfo is not a valid trigger';

        triggers.push(new MamiTextTrigger(triggerInfo));
    };

    const getTrigger = function(text, returnAlias) {
        for(const i in triggers) {
            let trigger = triggers[i];
            if(trigger.isMatch(text)) {
                if(trigger.isAliasType() && !returnAlias) {
                    const aliasFor = trigger.getFor();
                    trigger = getTrigger(aliasFor[Math.floor(Math.random() * aliasFor.length)]);
                }

                return trigger;
            }
        }

        throw 'no trigger that matches this text';
    };

    return {
        addTrigger: addTrigger,
        addTriggers: function(triggerInfos) {
            for(const i in triggerInfos)
                try {
                    addTrigger(triggerInfos[i]);
                } catch(ex) {
                    console.error(ex);
                }
        },
        clearTriggers: function() {
            triggers = [];
        },
        hasTriggers: function() {
            return triggers.length > 0;
        },
        getTrigger: getTrigger,
    };
};
