context: using System;
  using System.Collections.Generic;
  using System.Data.Linq.SqlClient;
  using System.Linq;
  using UtilityExtensions;
  using System.Linq.Expressions;
  namespace CmsData
  {
      public partial class Condition
      {
          public Dictionary<Guid, Condition> AllConditions { get; set; }
  
          #region Fields
  
          public Guid Id { get; set; }
          public Guid? ParentId { get; set; }
          public int Order { get; set; }
          public string ConditionName { get; set; }
          public string Comparison { get; set; }
          public string TextValue { get; set; }
          public DateTime? DateValue { get; set; }
          public string CodeIdValue { get; set; }
  
          private DateTime? startDate;
          public DateTime? StartDate
          {
              get
              {
                  if(db != null)
                      return db.QbStartDateOverride ?? startDate;
                  return startDate;
              }
              set { startDate = value; }
          }
  
          private DateTime? endDate;
          public DateTime? EndDate
          {
              get
              {
                  if(db != null)
                      return db.QbEndDateOverride ?? endDate;
                  return endDate;
              }
              set { endDate = value; }
          }
  
          public int Ministry { get; set; }
          public int Program { get; set; }
  
          private int division;
          public int Division
          {
              get
              {
                  if(db != null)
                      return db.QbDivisionOverride ?? division;
                  return division;
              }
              set { division = value; }
          }
  
          public int Organization { get; set; }
          public int Days { get; set; }
          public string Owner { get; set; }
          public string Description { get; set; }
          public string PreviousName { get; set; }
          public bool IsPublic { get; set; }
          public DateTime CreatedOn { get; set; }
          public string Quarters { get; set; }
          public string SavedQuery { get; set; }
          public string Tags { get; set; }
          public int Schedule { get; set; }
          public int? Age { get; set; }
          public int? Campus { get; set; }
          public int? OrgType { get; set; }
          public int? OrgType2 { get; set; }
          public string OrgName { get; set; }
          public int? OrgStatus { get; set; }
          public int? OnlineReg { get; set; }
          public Guid? NewMatchAnyId;
          internal Query JustLoadedQuery;
  
          #endregion
  
          public IEnumerable<Condition> Conditions
          {
              get
              {
                  var q = from c in AllConditions.Values
                          where c.ParentId == Id
                          orderby c.Order
                          select c;
                  return q;
              }
          }
          public Condition Parent
          {
              get
              {
                  if (ParentId.HasValue)
                      return AllConditions[ParentId.Value];
                  return null;
              }
          }
          private FieldClass2 _FieldInfo;
          public FieldClass2 FieldInfo
          {
              get
              {
                  try
                  {
                      if ((_FieldInfo == null || _FieldInfo.Name != ConditionName))
                          _FieldInfo = FieldClass2.Fields[ConditionName];
                      return _FieldInfo;
                  }
                  catch (Exception)
                  {
                      throw new Exception("QB Field not found: " + ConditionName);
                  }
              }
          }
          public void SetComparisonType(CompareType value)
          {
              Comparison = value.ToString();
          }
          public void SetQueryType(QueryType value)
          {
              ConditionName = value.ToString();
          }
          public CompareType ComparisonType
          {
              get { return CompareClass2.Convert(Comparison); }
          }
          private CompareClass2 compare;
          public CompareClass2 Compare2
          {
              get
              {
                  if (compare == null)
                      compare = CompareClass2.Comparisons.SingleOrDefault(cm =>
                          cm.FieldType == FieldInfo.Type && cm.CompType == ComparisonType);
                  return compare;
              }
          }
          public override string ToString()
          {
              string ret = "null";
              if (ConditionName == "MatchAnything")
                  ret = "Match Anything";
              switch (ComparisonType)
              {
                  case CompareType.AllTrue:
                      ret = "Match ALL of the conditions below";
                      break;
                  case CompareType.AnyTrue:
                      ret = "Match ANY of the conditions below";
                      break;
                  case CompareType.AllFalse:
                      ret = "Match NONE of the conditions below";
                      break;
                  default:
                      if (Compare2 != null)
                          ret = Compare2.ToString(this);
                      break;
              }
              return ret;
          }
  
          internal void SetIncludeDeceased()
          {
              var c = this;
              while (c.Parent != null)
                  c = c.Parent;
              c.includeDeceased = true;
          }
          internal void SetParentsOf(CompareType op, bool tf)
          {
              var c = this;
              while (c.Parent != null)
                  c = c.Parent;
              c.ParentsOf = ((tf && op == CompareType.Equal) || (!tf && op == CompareType.NotEqual));
          }
          internal void SetPlusParentsOf(CompareType op, bool tf)
          {
              var c = this;
              while (c.Parent != null)
                  c = c.Parent;
              c.PlusParentsOf = ((tf && op == CompareType.Equal) || (!tf && op == CompareType.NotEqual));
          }
          private bool includeDeceased = false;
          public bool ParentsOf { get; set; }
          public bool PlusParentsOf { get; set; }
          public Expression<Func<Person, bool>> Predicate(CMSDataContext db)
          {
              db.CopySession();
              var parm = Expression.Parameter(typeof(Person), "p");
              Expression tree;
  #if DEBUG
  #else
              try
              {
  #endif
                  tree = ExpressionTree(parm, db);
  #if DEBUG
  #else
              }
              catch (Exception ex)
              {
                  var x = ToXml();
                  throw new Exception("problem in query:\n" + x, ex);
              }
  #endif
              if (tree == null)
                  tree = CompareConstant(parm, "PeopleId", CompareType.NotEqual, 0);
              if (includeDeceased == false)
                  tree = Expression.And(tree, CompareConstant(parm, "IsDeceased", CompareType.NotEqual, true));
              if (Util2.OrgMembersOnly)
                  tree = Expression.And(OrgMembersOnly(db, parm), tree);
              else if (Util2.OrgLeadersOnly)
                  tree = Expression.And(OrgLeadersOnly(db, parm), tree);
              return Expression.Lambda<Func<Person, bool>>(tree, parm);
          }
          private Expression OrgMembersOnly(CMSDataContext db, ParameterExpression parm)
          {
              var tag = db.OrgMembersOnlyTag2();
              Expression<Func<Person, bool>> pred = p =>
                  p.Tags.Any(t => t.Id == tag.Id);
              return Expression.Convert(Expression.Invoke(pred, parm), typeof(bool));
          }
          private Expression OrgLeadersOnly(CMSDataContext db, ParameterExpression parm)
          {
              var tag = db.OrgLeadersOnlyTag2();
              Expression<Func<Person, bool>> pred = p =>
                  p.Tags.Any(t => t.Id == tag.Id);
              return Expression.Convert(Expression.Invoke(pred, parm), typeof(bool));
          }
          private bool InAllAnyFalse
          {
              get { return Parent.IsGroup && Parent.ComparisonType == CompareType.AllFalse; }
          }
          private bool AnyFalseTrue
          {
              get { return ComparisonType == CompareType.AnyTrue; }
          }
          private Expression ExpressionTree(ParameterExpression parm, CMSDataContext Db)
          {
              Expression expr = null;
              if (IsGroup)
              {
                  foreach (var clause in Conditions)
                  {
                      if (clause.FieldInfo.QueryType == QueryType.IncludeDeceased)
                      {
                          SetIncludeDeceased();
                          continue;
                      }
                      if (clause.FieldInfo.QueryType == QueryType.ParentsOf)
                      {
                          SetParentsOf(clause.ComparisonType, clause.CodeIds == "1");
                          continue;
                      }
                      if (clause.FieldInfo.QueryType == QueryType.PlusParentsOf)
                      {
                          SetPlusParentsOf(clause.ComparisonType, clause.CodeIds == "1");
                          continue;
                      }
                      if(clause.FieldInfo.QueryType == QueryType.DeceasedDate)
                          SetIncludeDeceased();
                      if (expr == null)
                          expr = clause.ExpressionTree(parm, Db);
                      else
                      {
                          var right = clause.ExpressionTree(parm, Db);
                          if (right != null)
                              expr = AnyFalseTrue 
                                  ? Expression.Or(expr, right) 
                                  : Expression.And(expr, right);
                      }
                  }
                  return expr;
              }
              expr = Compare2 == null 
                  ? AlwaysFalse() 
                  : GetExpression(parm, Db);
              if (InAllAnyFalse)
                  expr = Expression.Not(expr);
              return expr;
          }
          public bool HasMultipleCodes
          {
              get
              {
                  if (ConditionName == "MatchAnything")
                      return false;
                  var e = Compare2;
                  if (e == null)
                      return false;
                  return e.CompType == CompareType.OneOf
  
gt:                     || e.CompType == CompareType.NotOneOf;