define(['scripts/StringModifier'], function(StringModifier) {


    /**
     * Contains the suggestions for each component of the statement.
     */
    function StatementProposals(){

        var _this = this;
        _this.content = {};

        /**
         * Adds suggestions to the symbols not yet available in the content.
         * Splits the proposals from the indexers.
         * @param {object} statementComponents Object containing the mapping between the symbols making the statement and their proposals.
         */
        _this.addNewEntry = function(statementComponents){
            var recomposedStatement = "";
            for(var i = 0; i < statementComponents.length; i++) {
                //Recompose the full command.
                var currentSymbol = statementComponents[i].Name;
                if(!(currentSymbol[0] === "[") && recomposedStatement != ""){
                    recomposedStatement += ".";
                }
                recomposedStatement += currentSymbol;

                //Splits proposal from indexer properties
                var proposals = [];
                var indexers = [];
                if(statementComponents[i].CompletionProposals){
                    for(var j=0; j< statementComponents[i].CompletionProposals.length; j++){
                        var currentProposal = statementComponents[i].CompletionProposals[j];
                        if(currentProposal.Category === "Property" && currentProposal.IndexParameters.length >0){
                            indexers.push(currentProposal);
                        }else{
                            proposals.push(currentProposal);
                        }
                    }

                    //Add also substatements in the list of available proposals
                    // for (var k=0; k< statementComponents[i].GenericStatements.length; k++){
                    //     _this.addNewEntry(statementComponents[i].SubStatements[k]);
                    // }
                }
                _this.content[recomposedStatement] = {proposals: proposals, indexers: indexers, info: statementComponents[i].SymbolInfo};
            }
        };

        _this.containsStatementPart = function(statementPart){
            if(_this.content[statementPart])
            {
                return true;
            }
            return false;
        };

        _this.getProposals = function(statementPart){
            var fullProposals = _this.content[statementPart];
            if(!fullProposals){
                return [];
            }
            return fullProposals.proposals;
        };

        _this.getIndexers = function(statementPart){
            var fullProposals = _this.content[statementPart];
            if(!fullProposals){
                return [];
            }
            return fullProposals.indexers;
        };

        _this.getInfo = function(statementPart){
            var symbol = _this.content[statementPart];
            if(!symbol){
                return [];
            }
            return symbol.info;
        };

        /**
         * Retrieves the symbol(s) information from the last component of the statementPart.(Several symbols can be found in case of overloaded method.)
         * @param {string} statementPart The full statementPart to analyze.
         * @returns {array} The symbolInfo if found.  '__SymbolNotFound__' if the symbol is not present in the suggestions. An empty array if there is no suggestions.
         */
        _this.getSymbolInfoFromProposals = function(statementPart){
            var symbolsInfo = [];
            var symbols = StringModifier.SplitExceptInsideBrackets(statementPart, "\\.");
            var lastSymbol = symbols.pop();
            var pattern = new RegExp("[\[\(]");
            lastSymbol = lastSymbol.split(pattern)[0];
            var commandInfo = _this.content[symbols.join('.')];
            if(commandInfo){
                var proposals =  commandInfo ? commandInfo.proposals : null;
                if(proposals){
                    for (var i=0; i< proposals.length; i++){
                        if(proposals[i].Name === lastSymbol){
                            symbolsInfo.push(proposals[i]);
                        }
                    }
                }else{
                    symbolsInfo = "__SymbolNotFound__";
                }
            }
            return symbolsInfo;
        };


        /**
         * Tells wether the last component of the statementPart contains generic parameters.
         * @param {string} statementPart The full statementPart.
         * @returns {boolean} true if it contains generic parameters. false if not. undefined if the symbol is not known yet.
         */
        _this.doesLastSymbolContainGenericParameters = function(statementPart){
            var symbolsInfo = _this.content[statementPart];
            if(symbolsInfo.info.length === 0){
                return undefined;
            }
            for (var i=0; i< symbolsInfo.info.length; i++){
                var symbolInfo = symbolsInfo.info[i];
                if(symbolInfo.Category === "Method" && symbolInfo.ContainsGenericParameters){
                    return true; 
                }
                if(symbolInfo.Category === "Type" && symbolInfo.IsGeneric){
                    return true;
                }
            }
            return false;
        };


        /**
         * Specifies whether a square bracket after the last symbol of the command would be an indexer or a generic method.
         * @param {string} command the command to analyze.
         * @returns {string} returns "generic", "indexer" or "undefined".
         */
        _this.isIndexerOrGenericBracket = function(command){
            var isIndexerOrGenericBracket = "undefined";
            if(_this.containsStatementPart(command)){
                if(_this.doesLastSymbolContainGenericParameters(command)){
                    var lastSymbol = StringModifier.SplitExceptInsideBrackets(command, "\\.");
                    //If another '[', it cannot be generic since generic brackets have already been consumed.
                    if(lastSymbol.pop().indexOf("[") < 0 ){
                        isIndexerOrGenericBracket = "generic";
                    }else{
                        isIndexerOrGenericBracket = "indexer";
                    }
                }else{
                    isIndexerOrGenericBracket = "indexer";
                }
            }
            return isIndexerOrGenericBracket;
        };


        _this.countOverloads = function(statementPart){
            var symbolsInfo = _this.content[statementPart];
            return symbolsInfo.length;
        };

    }

    return StatementProposals;
});
