//----------------------------------------------------------------------------------------
// nonTerminal constructor
var nonTerminal = function () {
    var that = {};
    
    // Private vars
    var productions = [];
    var totalWeight = 0;
    
    // Method addProduction: Creates a new production object and stores it in the internal
    //      productions array.
    // source - a line of text representing a production; the format is a line of text not
    //      containing any ":" characters, optionally followed by a ":" and a numeric
    //      weight value
    that.addProduction = function (source) {
        var weight = 1;
        var text = source;
        
        var parts = source.split(":");
        
        if (parts.length > 1) {
            text = parts[0];
            weight = parseInt(parts[1], 10);
        }
        
        productions.push({"text": text, "weight": weight});
        totalWeight += weight;
    };
    
    // Method gimmeOne: Randomly chooses a production from among the ones in the vector,
    //      taking weight into consideration, and returns its text.
    that.gimmeOne = function () {
        if (productions.length === 0) {
            return "";
        }
        
        var rand = Math.floor(Math.random() * totalWeight) + 1;
        var index = -1;
        
        var n;
        for (n = 0; (n < productions.length) && (index === -1); n += 1) {
            rand -= productions[n].weight;
            
            if (rand <= 0) {
                index = n;
            }
        }
        
        return productions[index].text;
    };
    
    return that;
};

//----------------------------------------------------------------------------------------
// zendomizer constructor
// fileUrl - a URL to a grammar file
var zendomizer = function (fileUrl) {
    var that = {};
    
    // Private vars
    var nonTerminals = {};
    var startNonTerm = null;

    // Read the grammar file and create the nonTerminals
    (function () {
        var currNonTerm = null;
        var nonTermName;
        var lines;
        var line;
        var n;
        
        lines = readFile(fileUrl).split("\n");

        for (n = 0; n < lines.length; n += 1) {
            line = lines[n].trim();
            
            if (line.length === 0) {
                // Skip
            } else if (line.charAt(0) === "#") {
                nonTermName = line.slice(1);
                
                if (nonTermName.length > 0) {
                    // Create and store the new nonTerminal
                    currNonTerm = nonTerminal();
                    nonTerminals[nonTermName] = currNonTerm;
                    
                    // If this is the first nonTerm created, store it as the starting one
                    if (startNonTerm === null) {
                        startNonTerm = currNonTerm;
                    }
                }
            } else if (currNonTerm !== null) {
                currNonTerm.addProduction(line);
            }
        }
    })();
    
    // Method generateText: Generates and returns a new random Zendo rule.
    that.generateText = function () {
        var output = startNonTerm.gimmeOne();
        
        while (output.indexOf("<") > -1) {
            output = output.replace(/<[^>]+>/, function (nts) {
                return nonTerminals[nts.slice(1, nts.length - 1)].gimmeOne();
            });
        }
        
        return output;
    };
    
    return that;
};

