private static void ParseClusters(Context context)
        {
            while (context.Lines.Count > 0)
            {
                string line = context.Lines[0];
                context.Lines.RemoveAt(0);

                // Returning to previous level.
                if (line.StartsWith("# "))
                {
                    context.Lines.Insert(0, line);
                    return;
                }

                if (line.StartsWith("## "))
                {
                    context.Cluster                    = new Cluster();
                    context.Cluster.ClusterName        = GetHeaderTitle(line);
                    context.Cluster.ClusterDescription = new List <string>();
                    context.Cluster.ClusterType        = CodeGeneratorUtil.LabelToEnumerationValue(context.Cluster.ClusterName);
                    context.Cluster.ClusterId          = GetHeaderId(line);
                    context.Cluster.NameUpperCamelCase = CodeGeneratorUtil.LabelToUpperCamelCase(context.Cluster.ClusterName);
                    context.Cluster.NameLowerCamelCase = CodeGeneratorUtil.UpperCamelCaseToLowerCamelCase(context.Cluster.ClusterName);
                    context.Profile.Clusters.Add(context.Cluster.ClusterId, context.Cluster);
                    Console.WriteLine("  (" + CodeGeneratorUtil.ToHex(context.Cluster.ClusterId) + ") " + context.Cluster.ClusterName);

                    ParseDirections(context);
                }
            }
        }
        private static void ParseCommands(Context context)
        {
            bool  addBreak = false;
            Field field    = null;

            while (context.Lines.Count > 0)
            {
                string line = context.Lines[0];
                context.Lines.RemoveAt(0);

                // Returning to previous level.
                if (line.StartsWith("# ") || line.StartsWith("## ") || line.StartsWith("### "))
                {
                    context.Lines.Insert(0, line);
                    return;
                }

                if (line.StartsWith("##### Expected Response"))
                {
                    ParseExpectedResponse(context);
                    continue;
                }

                if (line.StartsWith("##### "))
                {
                    addBreak = false;

                    foreach (Field fieldLoop in context.Command.Fields.Values)
                    {
                        if (fieldLoop.FieldLabel.Equals(line.Trim().Substring(6)))
                        {
                            field = fieldLoop;
                            break;
                        }
                    }
                    if (field == null)
                    {
                        Console.WriteLine("Error finding field \"" + line.Trim().Substring(6) + "\"");
                    }
                    continue;
                }

                if (line.StartsWith("#### "))
                {
                    context.Command = new Command();
                    context.Command.CommandLabel = GetHeaderTitle(line).Trim();
                    string[] splits = context.Command.CommandLabel.Split(" ");

                    if ("RESPONSE".Equals(splits[splits.Length - 2].ToUpper()) && "COMMAND".Equals(splits[splits.Length - 1].ToUpper()))
                    {
                        StringBuilder sb = new StringBuilder();
                        for (int c = 0; c < splits.Length - 1; c++)
                        {
                            if (c != 0)
                            {
                                sb.Append(" ");
                            }
                            sb.Append(splits[c]);
                        }

                        context.Command.CommandLabel = sb.ToString();
                    }

                    context.Command.CommandDescription = new List <string>();
                    context.Command.CommandType        = CodeGeneratorUtil.LabelToEnumerationValue(context.Command.CommandLabel);
                    context.Command.CommandId          = GetHeaderId(line);
                    context.Command.NameUpperCamelCase = CodeGeneratorUtil.LabelToUpperCamelCase(context.Command.CommandLabel);
                    context.Command.NameLowerCamelCase = CodeGeneratorUtil.UpperCamelCaseToLowerCamelCase(context.Command.NameUpperCamelCase);

                    if (context.Received)
                    {
                        context.Cluster.Received.Add(context.Command.CommandId, context.Command);
                    }
                    else
                    {
                        context.Cluster.Generated.Add(context.Command.CommandId, context.Command);
                    }

                    Console.WriteLine("     (" + CodeGeneratorUtil.ToHex(context.Command.CommandId) + ") " + context.Command.CommandLabel);

                    ParseField(context);
                    continue;
                }

                if (field == null)
                {
                    continue;
                }

                if (line.StartsWith("|") && !line.StartsWith("|Id") && !line.StartsWith("|-"))
                {
                    string   row     = line.Trim().Substring(1, line.Length - 1);
                    string[] columns = row.Split("|");
                    int      value   = int.Parse(columns[0].Trim().Substring(2), System.Globalization.NumberStyles.HexNumber);
                    string   label   = columns[1].Trim();

                    field.ValueMap.Add(value, label);
                    continue;
                }
                if (line.StartsWith("|") && (line.StartsWith("|Id") || line.StartsWith("|-")))
                {
                    continue;
                }

                if (field.Description.Count == 0 && line.Trim().Length == 0)
                {
                    continue;
                }
                if (line.Trim().Length == 0)
                {
                    addBreak = true;
                    continue;
                }
                if (addBreak && field.Description.Count > 0)
                {
                    field.Description.Add("<p>");
                    addBreak = false;
                }
                field.Description.Add(line.Trim());
            }
        }
        private static void ParseField(Context context)
        {
            int  fieldIndex = 0;
            bool addBreak   = false;

            while (context.Lines.Count > 0)
            {
                string line = context.Lines[0];
                context.Lines.RemoveAt(0);

                // Returning to previous level.
                if (line.StartsWith("#"))
                {
                    context.Lines.Insert(0, line);
                    return;
                }

                if (line.StartsWith("|") && !line.StartsWith("|Field Name") && !line.StartsWith("|-"))
                {
                    string   row     = line.Trim().Substring(1, line.Length - 1);
                    string[] columns = row.Split("|");//row.Split("\\|");
                    Field    field   = new Field();
                    field.Description = new List <string>();
                    field.FieldId     = fieldIndex;
                    field.ValueMap    = new SortedDictionary <int, string>();

                    field.FieldLabel = columns[0].Trim();
                    if (field.FieldLabel.Contains("["))
                    {
                        string option = field.FieldLabel.Substring(field.FieldLabel.IndexOf("[") + 1, field.FieldLabel.IndexOf("]"));
                        field.FieldLabel     = field.FieldLabel.Substring(0, field.FieldLabel.IndexOf("["));
                        field.CompleteOnZero = true;
                    }

                    field.FieldType = context.Command.CommandType + "_" + CodeGeneratorUtil.LabelToEnumerationValue(field.FieldLabel);
                    //field.NameUpperCamelCase = CodeGeneratorUtil.LabelToEnumerationValue(field.FieldLabel);
                    field.NameUpperCamelCase = CodeGeneratorUtil.LabelToUpperCamelCase(field.FieldLabel);
                    field.NameLowerCamelCase = CodeGeneratorUtil.UpperCamelCaseToLowerCamelCase(field.NameUpperCamelCase);

                    string dataTypeName = columns[1].Trim();
                    if (dataTypeName.Contains("["))
                    {
                        string fieldString = SubstringBetween(dataTypeName, "[", "]"); //dataTypeName.Substring(dataTypeName.IndexOf("[") + 1, dataTypeName.IndexOf("]"));

                        if (fieldString.Length != 0)
                        {
                            string conditionOperator = "";
                            string condition         = "";
                            if (fieldString.Contains("&&"))
                            {
                                conditionOperator = "&&";
                            }
                            if (fieldString.Contains(">="))
                            {
                                conditionOperator = ">=";
                            }
                            if (fieldString.Contains("=="))
                            {
                                conditionOperator = "==";
                            }

                            if (conditionOperator.Length != 0)
                            {
                                field.ListSizer = fieldString.Substring(0, fieldString.IndexOf(conditionOperator));
                                condition       = fieldString
                                                  .Substring(fieldString.IndexOf(conditionOperator) + conditionOperator.Length);

                                field.Condition         = condition;
                                field.ConditionOperator = conditionOperator;
                            }
                            else
                            {
                                field.ListSizer = fieldString;
                            }

                            field.ListSizer = CodeGeneratorUtil.LabelToUpperCamelCase(field.ListSizer);
                            field.ListSizer = CodeGeneratorUtil.UpperCamelCaseToLowerCamelCase(field.ListSizer);

                            dataTypeName = dataTypeName.Substring(0, dataTypeName.IndexOf("["));
                        }
                    }

                    field.DataType = CodeGeneratorUtil.LabelToEnumerationValue(dataTypeName);

                    DataType dataType = new DataType();
                    dataType.DataTypeName = dataTypeName;
                    dataType.DataTypeType = field.DataType;

                    dataType.DataTypeClass = ZclDataType.Mapping[field.DataType].DataClass;
                    if (dataType.DataTypeClass == null)
                    {
                        throw new InvalidOperationException("Type not mapped: " + field.DataType);
                    }

                    field.DataTypeClass = dataType.DataTypeClass;

                    context.DataTypes[field.DataType] = dataType;
                    context.Command.Fields.Add(field.FieldId, field);
                    Console.WriteLine("      (" + CodeGeneratorUtil.ToHex(fieldIndex) + ") " + field.FieldLabel + ": " + dataType.DataTypeName);
                    fieldIndex++;
                }

                if (line.StartsWith("|Id") || line.StartsWith("|-"))
                {
                    continue;
                }

                if (line.StartsWith("|"))
                {
                    addBreak = false;
                    continue;
                }

                if (context.Command.CommandDescription.Count == 0 && line.Trim().Length == 0)
                {
                    continue;
                }
                if (line.Trim().Length == 0)
                {
                    addBreak = true;
                    continue;
                }
                if (addBreak)
                {
                    context.Command.CommandDescription.Add("<br>");
                    addBreak = false;
                }
                context.Command.CommandDescription.Add(line.Trim());
            }
        }
        public static void ParseProfiles(Context context)
        {
            while (context.Lines.Count > 0)
            {
                string line = context.Lines[0];
                context.Lines.RemoveAt(0);

                if (line.StartsWith("# ") && line.Contains("["))
                {
                    context.Profile = new Profile
                    {
                        ProfileName         = GetHeaderTitle(line),
                        ProfileAbbreviation = GetHeaderAbbreviation(line)
                    };
                    context.Profile.ProfileType = CodeGeneratorUtil.LabelToEnumerationValue(context.Profile.ProfileName);
                    context.Profile.ProfileId   = GetHeaderId(line);
                    context.Profiles.Add(context.Profile.ProfileId, context.Profile);

                    Console.WriteLine("Profile: " + context.Profile.ProfileName + " " + CodeGeneratorUtil.ToHex(context.Profile.ProfileId));

                    ParseFunctionalDomains(context);
                }
            }
        }