/*public static List<String> getListOfUniqueSignatures_UsingUniqueList(List<IO2Finding> o2Findings)
         * {
         *  // mode 1 use one big list
         *  var uniqueSignatures = new List<String>();
         *  // calculate unique signatures
         *  var itemsProcessed = 0;
         *  var itemsToProcess = o2Findings.Count;
         *  foreach (var o2Finding in o2Findings)
         *  {
         *      getListOfUniqueSignatures(o2Finding.o2Traces, uniqueSignatures);
         *      if ((itemsProcessed++) % 5000 == 0)
         *          DI.log.info("on [{0}/{1}] there are {2} unique signatures", itemsProcessed, itemsToProcess, uniqueSignatures.Count);
         *  }
         *  DI.log.info("There are {0} unique signatures", uniqueSignatures.Count);
         *  return uniqueSignatures;
         * }*/



        internal static O2RulePack mapFindingsToCurrentRulePack(
            O2RulePack currentO2RulePack, List <IO2Finding> o2Findings, string languageId, bool keepRulesLoadedFromDatabase)
        {
            var newCallbackSignature = "O2.AutoMapping";

            DI.log.info("converting {0} Findings into rules", o2Findings.Count);

            // get rules that we will keep (if there are rules loaded from Db and keepRulesLoadedFromDatabase is set)
            var newO2Rules = (keepRulesLoadedFromDatabase)
                                 ? O2RulePackUtils.getRulesThatAreFromDB(currentO2RulePack)
                                 : new List <IO2Rule>();

            //update index
            var indexedCurrentO2Rules = IndexedO2Rules.indexAll(newO2Rules);

            // and if there are any rules from the database, remove any Tagged values
            if (keepRulesLoadedFromDatabase)
            {
                foreach (var o2Rule in newO2Rules)
                {
                    o2Rule.Tagged = false;
                }
            }

            // create rulepack
            var newRulePack = new O2RulePack("Rule Pack", newO2Rules);

            // and call the function that does the mappings
            mapInRulePack_FindingsSourcesAndSinks(newRulePack, indexedCurrentO2Rules, o2Findings, languageId);

            DI.log.info("{0} rules created", newRulePack.o2Rules.Count);

            return(newRulePack);
        }
        public static O2RulePack createRulePackWithSignatures(O2RulePack o2rulePack, List <String> signaturesToFind, string rulePackName, bool addNonMatchingSignaturesAsNewRule, string languageDBId)
        {
            DI.log.info("in createRulePackWithSignatures");
            var o2RulesThatMatchSignatures = new List <IO2Rule>();
            var indexedRules = IndexedO2Rules.indexAll(o2rulePack.getIO2Rules());

            foreach (var signature in signaturesToFind)
            {
                if (indexedRules.ContainsKey(signature))
                {
                    foreach (var o2Rule in indexedRules[signature])
                    {
                        o2RulesThatMatchSignatures.Add(o2Rule);
                    }
                }
                else
                if (addNonMatchingSignaturesAsNewRule)
                {
                    o2RulesThatMatchSignatures.Add(O2RulePackUtils.createRule(O2RuleType.NotMapped, signature, languageDBId));
                }
            }
            DI.log.info("createRulePackWithSignatures completed, there were {0} rules found", o2RulesThatMatchSignatures.Count);
            return(new O2RulePack(rulePackName, o2RulesThatMatchSignatures));
        }
        //rename this method since we do more than just Source or Sinks here
        private static void updateSourceOrSinkRule(O2RulePack o2RulePack, IDictionary <string, List <IO2Rule> > indexedO2Rules, string ruleSignature, string languageDBId, TraceType traceType)
        {
            if (indexedO2Rules != null && ruleSignature != null)
            {
                //bool createNotMappedRule = false;
                var createRuleWithType = O2RuleType.NotMapped;
                // only proccess Sources, Sinks and Lost Sinks
                if (traceType == TraceType.Source || traceType == TraceType.Known_Sink || traceType == TraceType.Lost_Sink)
                {
                    O2RuleType o2NewRuleType = O2RulePackUtils.getO2RuleTypeFromRuleType(traceType);
                    createRuleWithType = o2NewRuleType;

                    /*       if (indexedO2Rules != null && false == string.IsNullOrEmpty(ruleSignature))
                     *         if (indexedO2Rules.ContainsKey(ruleSignature))
                     *         {
                     *             bool thereIsAlreadyARuleWithTheSameRuleType = false;
                     *             foreach (var o2Rule in indexedO2Rules[ruleSignature])
                     *             {
                     *                 if (o2Rule.RuleType == O2RuleType.NotMapped)
                     *                 // if it is not mapped change it to o2NewRuleType
                     *                 {
                     *                     o2Rule.RuleType = o2NewRuleType;
                     *                     return;
                     *                 }
                     *                 if (o2Rule.RuleType == o2NewRuleType)
                     *                     // if it is already a rule of type o2NewRuleType, mark it so we can ignore it below
                     *                     thereIsAlreadyARuleWithTheSameRuleType = true;
                     *             }
                     *             if (false == thereIsAlreadyARuleWithTheSameRuleType)
                     *             // if we got this far, create a new rule of o2NewRuleType
                     *             {
                     *                 var newRule = O2RulePackUtils.createRule(o2NewRuleType, ruleSignature, languageDBId);
                     *                 indexedO2Rules[ruleSignature].Add(newRule);
                     *                 // add it to the index so that we don't have to calculate it again
                     *                 o2RulePack.o2Rules.Add(newRule);
                     *             }
                     *         }
                     */
                }
                bool    createNewRule = true;
                IO2Rule notMappedRule = null;

                if (indexedO2Rules.ContainsKey(ruleSignature))
                {
                    foreach (var o2Rule in indexedO2Rules[ruleSignature])
                    {
                        if (o2Rule.RuleType == createRuleWithType)          // dont create if there is already a rule of this type
                        {
                            o2Rule.Tagged = true;
                            createNewRule = false;
                        }
                        if (o2Rule.RuleType == O2RuleType.NotMapped)
                        {
                            notMappedRule = o2Rule;
                        }
                    }
                }
                // handle the case where we have already added a signature but it is not a NotMapped one
                if (createRuleWithType == O2RuleType.NotMapped && createNewRule && notMappedRule == null && indexedO2Rules.ContainsKey(ruleSignature))
                {
                    createNewRule = false;
                }

                // if required, Create  rule
                if (createNewRule)
                {
                    var vulnType = "O2.FindingRule." + createRuleWithType.ToString();
                    var newRule  = new O2Rule(createRuleWithType, vulnType, ruleSignature, languageDBId, true);
                    o2RulePack.o2Rules.Add(newRule);
                    if (false == indexedO2Rules.ContainsKey(ruleSignature))
                    {
                        indexedO2Rules.Add(ruleSignature, new List <IO2Rule>());
                    }
                    indexedO2Rules[ruleSignature].Add(newRule);
                    if (notMappedRule != null)
                    {
                        indexedO2Rules[ruleSignature].Remove(notMappedRule);
                    }
                }
            }
        }