public static Dictionary<string, object> ExportMassToGBXML(string FilePath, AbstractFamilyInstance MassFamilyInstance, List<AbstractFamilyInstance> MassShadingInstances, Boolean Run = false)
        {
            // Local variables
            Boolean IsSuccess = false;
            string FileName = string.Empty;
            string Folder = string.Empty;

            // Check if path and directory valid
            if (System.String.IsNullOrEmpty(FilePath) || FilePath == "No file selected.")
            {
                throw new Exception("No File selected !");
            }

            FileName = Path.GetFileNameWithoutExtension(FilePath);
            Folder = Path.GetDirectoryName(FilePath);

            // Check if Directory Exists
            if (!Directory.Exists(Folder))
            {
                throw new Exception("Folder doesn't exist. Input valid Directory Path!");
            }

            //make RUN? inputs set to True mandatory
            if (Run == false)
            {
                throw new Exception("Set 'Connect' to True!");
            }

            //local variables
            Document RvtDoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument.Document;

            //enable the analytical model in the document if it isn't already
            try
            {
                PrepareEnergyModel.ActivateEnergyModel(RvtDoc);
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to enable the energy model.");
            }

            //get the id of the analytical model associated with that mass
            Autodesk.Revit.DB.ElementId myEnergyModelId = MassEnergyAnalyticalModel.GetMassEnergyAnalyticalModelIdForMassInstance(RvtDoc, MassFamilyInstance.InternalElement.Id);
            if (myEnergyModelId.IntegerValue == -1)
            {
                throw new Exception("Could not get the MassEnergyAnalyticalModel from the mass - make sure the Mass has at least one Mass Floor.");
            }
            MassEnergyAnalyticalModel mea = (MassEnergyAnalyticalModel)RvtDoc.GetElement(myEnergyModelId);
            ICollection<Autodesk.Revit.DB.ElementId> ZoneIds = mea.GetMassZoneIds();

            // get shading Ids
            List<Autodesk.Revit.DB.ElementId> ShadingIds = new List<Autodesk.Revit.DB.ElementId>();
            for (int i = 0; i < MassShadingInstances.Count(); i++)
            {

            // make sure input mass is valid as a shading
            if (MassInstanceUtils.GetMassLevelDataIds(RvtDoc, MassShadingInstances[i].InternalElement.Id).Count() > 0)
            {
                throw new Exception("Item " + i.ToString() + " in MassShadingInstances has mass floors assigned. Remove the mass floors and try again.");
            }

            ShadingIds.Add(MassShadingInstances[i].InternalElement.Id);
            }

            if (ShadingIds.Count != 0)
            {
                MassGBXMLExportOptions gbXmlExportOptions = new MassGBXMLExportOptions(ZoneIds.ToList(), ShadingIds); // two constructors
                RvtDoc.Export(Folder, FileName, gbXmlExportOptions);

            }
            else
            {
                MassGBXMLExportOptions gbXmlExportOptions = new MassGBXMLExportOptions(ZoneIds.ToList()); // two constructors
                RvtDoc.Export(Folder, FileName, gbXmlExportOptions);
            }

            // if the file exists return success message if not return failed message
            string path = Path.Combine(Folder, FileName + ".xml");

            if (System.IO.File.Exists(path))
            {
                // Modify the xml Program Info element, aithorize the
                XmlDocument doc = new XmlDocument();
                doc.Load(path);

                // EE: There must be a shorter way !
                XmlNode node = doc.DocumentElement;

                foreach (XmlNode node1 in node.ChildNodes)
                {
                    foreach (XmlNode node2 in node1.ChildNodes)
                    {
                        if (node2.Name == "ProgramInfo")
                        {
                            foreach (XmlNode childnode in node2.ChildNodes)
                            {
                                if (childnode.Name == "ProductName")
                                {
                                    string productname = "Dynamo _ " + childnode.InnerText;
                                    childnode.InnerText = productname;
                                }
                            }

                        }
                    }
                }

                //doc.DocumentElement.Attributes["ProgramInfo"].ChildNodes[1].Value += "Dynamo ";
                doc.Save(path);

                IsSuccess = true;
            }
            string message = "Failed to create gbXML file!";

            if (IsSuccess)
            {
                message = "Success! The gbXML file was created";
            }
            else
            {
                path = string.Empty;
            }

            // Populate Output Values
            return new Dictionary<string, object>
            {
                { "report", message},
                { "gbXMLPath", path}
            };
        }
        public static Dictionary<string, object> CreateByMass(AbstractFamilyInstance MassFamilyInstance)
        {
            //local varaibles
            Document RvtDoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument.Document;

            //enable the analytical model in the document if it isn't already
            try
            {
                ActivateEnergyModel(RvtDoc);
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to enable the energy model.");
            }

            //get the id of the analytical model associated with that mass
            Autodesk.Revit.DB.ElementId myEnergyModelId = MassEnergyAnalyticalModel.GetMassEnergyAnalyticalModelIdForMassInstance(RvtDoc, MassFamilyInstance.InternalElement.Id);
            MassEnergyAnalyticalModel mea = (MassEnergyAnalyticalModel)RvtDoc.GetElement(myEnergyModelId);

            //throw an error if we can't get the analytical model - it must be enabled in Revit.
            if (mea == null)
            {
                throw new Exception("Could not get the MassEnergyAnalyticalModel from the mass - make sure the Mass has at least one Mass Floor.");
            }

            //get the zone ids from our Mass's MassEnergyAnalyticalModel object
            //we'll use these to draw zones in another component - not sure if we can use them to drive opening / shading params
            List<Autodesk.Revit.DB.ElementId> zoneIds = mea.GetMassZoneIds().ToList();

            //loop over the output lists, and wrap them in our ElementId wrapper class
            List<ElementId> outZoneIds = zoneIds.Select(e => new ElementId(e.IntegerValue)).ToList();

            return new Dictionary<string, object>
            {
                {"MassFamilyInstance", MassFamilyInstance},
                {"ZoneIds", outZoneIds}
            };
        }
        public static Dictionary<string, object> CreateByMassLevels(AbstractFamilyInstance MassFamilyInstance, List<Revit.Elements.Element> Levels)
        {
            //local varaibles
            Document RvtDoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument.Document;
            EnergyAnalysisDetailModel em = null;

            #region Mass Floors and Energy Model
            //create mass floors
            try
            {
                TransactionManager.Instance.EnsureInTransaction(RvtDoc);
                foreach (var l in Levels)
                {
                    MassInstanceUtils.AddMassLevelDataToMassInstance(RvtDoc, MassFamilyInstance.InternalElement.Id, l.InternalElement.Id);
                }
                TransactionManager.Instance.TransactionTaskDone();
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to create mass floors.");
            }

            //enable the analytical model in the document if it isn't already
            try
            {
                ActivateEnergyModel(RvtDoc);
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to enable the energy model.");
            }

            //try to create an energy analysis model in the document
            try
            {
                TransactionManager.Instance.EnsureInTransaction(RvtDoc);
                EnergyAnalysisDetailModelOptions opt = new EnergyAnalysisDetailModelOptions();
                opt.Tier = EnergyAnalysisDetailModelTier.NotComputed;
                em = EnergyAnalysisDetailModel.Create(RvtDoc, opt);
                TransactionManager.Instance.TransactionTaskDone();
                DocumentManager.Regenerate();
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to create an energy model from your mass.");
            }
            #endregion

            #region Output Zone and Surface IDs
            //ok now we should be able to get all of the zones and surfaces associated
            //with our mass, and output them for use downstream

            //get the id of the analytical model associated with that mass
            Autodesk.Revit.DB.ElementId myEnergyModelId = MassEnergyAnalyticalModel.GetMassEnergyAnalyticalModelIdForMassInstance(RvtDoc, MassFamilyInstance.InternalElement.Id);
            MassEnergyAnalyticalModel mea = (MassEnergyAnalyticalModel)RvtDoc.GetElement(myEnergyModelId);

            //if mea is null, we should throw a good error message.  Seems to be working in Revit now that we are regenerating.
            if (mea == null)
            {
                throw new Exception("Could not get the MassEnergyAnalyticalModel from the mass.");
            }

            //get the zone ids from our Mass's MassEnergyAnalyticalModel object
            //we'll use these to draw zones in another component - not sure if we can use them to drive opening / shading params
            List<Autodesk.Revit.DB.ElementId> zoneIds = mea.GetMassZoneIds().ToList();
            //loop over the output lists, and wrap them in our ElementId wrapper class
            List<ElementId> outZoneIds = zoneIds.Select(e => new ElementId(e.IntegerValue)).ToList();

            #endregion

            return new Dictionary<string, object>
            {
                {"MassFamilyInstance", MassFamilyInstance},
                {"ZoneIds", outZoneIds}
            };
        }
        public static Dictionary<string, object> ExportMassToGBXML(string FilePath, AbstractFamilyInstance MassFamilyInstance, Boolean Run = false)
        {
            Boolean IsSuccess = false;

            string FileName = Path.GetFileNameWithoutExtension(FilePath);
            string Folder = Path.GetDirectoryName(FilePath);

            //make RUN? inputs set to True mandatory
            if (Run == false)
            {
                throw new Exception("Set 'Connect' to True!");
            }

            //local variables
            Document RvtDoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument.Document;

            //enable the analytical model in the document if it isn't already
            try
            {
                PrepareEnergyModel.ActivateEnergyModel(RvtDoc);
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to enable the energy model.");
            }

            //get the id of the analytical model associated with that mass
            Autodesk.Revit.DB.ElementId myEnergyModelId = MassEnergyAnalyticalModel.GetMassEnergyAnalyticalModelIdForMassInstance(RvtDoc, MassFamilyInstance.InternalElement.Id);
            MassEnergyAnalyticalModel mea = (MassEnergyAnalyticalModel)RvtDoc.GetElement(myEnergyModelId);
            ICollection<Autodesk.Revit.DB.ElementId> ZoneIds = mea.GetMassZoneIds();

            MassGBXMLExportOptions gbXmlExportOptions = new MassGBXMLExportOptions(ZoneIds.ToList()); // two constructors 

            RvtDoc.Export(Folder, FileName, gbXmlExportOptions);


            // if the file exists return success message if not return failed message
            string path = Path.Combine(Folder, FileName + ".xml");

            if (System.IO.File.Exists(path))
            {
                // Modify the xml Program Info element, aithorize the
                XmlDocument doc = new XmlDocument();
                doc.Load(path);

                // EE: There must be a shorter way !
                XmlNode node = doc.DocumentElement;

                foreach (XmlNode node1 in node.ChildNodes)
                {
                    foreach (XmlNode node2 in node1.ChildNodes)
                    {
                        if (node2.Name == "ProgramInfo")
                        {
                            foreach (XmlNode childnode in node2.ChildNodes)
                            {
                                if (childnode.Name == "ProductName")
                                {
                                    string productname = "Dynamo _ " + childnode.InnerText;
                                    childnode.InnerText = productname;
                                }
                            }

                        }
                    }
                }

                //doc.DocumentElement.Attributes["ProgramInfo"].ChildNodes[1].Value += "Dynamo ";
                doc.Save(path);

                IsSuccess = true;
            }
            string message = "Failed to create gbXML file!";

            if (IsSuccess)
            {
                message = "Success! The gbXML file was created";
            }
            else
            {
                path = string.Empty;
            }

            // Populate Output Values
            return new Dictionary<string, object>
            {
                { "report", message},
                { "gbXMLPath", path} 
            };
        }