private LightSetup GetLightSetup(ILightSetupPlugin plugin)
        {
            LightSetup lightSetup = new LightSetup();

            if (plugin.Lights != null && plugin.Lights.Any())
            {
                //convert back to 2d array for setup
                lightSetup.LightRows = new List<LightRow>();

                lightSetup.NumberOfRows = plugin.Lights.Max(l => l.Top);
                lightSetup.NumberOfColumns = plugin.Lights.Max(l => l.Left);

                for (int row = 0; row <= lightSetup.NumberOfRows; row++)
                {
                    LightRow lightRow = new LightRow();
                    lightRow.RowIndex = row;
                    lightRow.LightColumns = new List<LightColumn>();
                    for (int column = 0; column <= lightSetup.NumberOfColumns; column++)
                    {
                        LightColumn lightColumn = new LightColumn();
                        lightColumn.ColumnIndex = column;
                        if (column == 0 || column == lightSetup.NumberOfColumns
                            || row == 0 || row == lightSetup.NumberOfRows)
                        {

                            Light light = (from l in plugin.Lights
                                           where l.Top == row
                                               && l.Left == column
                                           select l).FirstOrDefault();
                            if (light != null)
                            {
                                lightColumn.Id = light.Id.ToString();
                                lightColumn.Index = light.Index.ToString();

                                lightColumn.Enabled = !string.IsNullOrEmpty(lightColumn.Id);
                            }
                        }
                        else
                        {
                            lightColumn.Enabled = false;
                        }

                        lightRow.LightColumns.Add(lightColumn);
                    }
                    lightSetup.LightRows.Add(lightRow);
                }
            }
            return lightSetup;
        }
        private PluginProperty[] GetPluginProperties(object plugin)
        {
            List<PluginProperty> pluginProperties = new List<PluginProperty>();

            if (plugin == null)
            {
                return pluginProperties.ToArray();
            }

            Type pluginObjectType = plugin.GetType();

            foreach (System.Reflection.PropertyInfo objectProperty in pluginObjectType.GetProperties())
            {
                PluginProperty pluginProperty = new PluginProperty();
                bool exclude = false;
                bool dataMember = false;

                if (!objectProperty.CanWrite)
                {
                    continue;
                }

                pluginProperty.Name = objectProperty.Name;

                pluginProperty.Value = objectProperty.GetValue(plugin, null);

                Type propertyType = objectProperty.PropertyType;
                if (propertyType == typeof(string))
                {
                    pluginProperty.Type = "text";
                }
                else if (propertyType == typeof(int))
                {
                    pluginProperty.Type = "number";
                }
                else if (propertyType == typeof(bool))
                {
                    pluginProperty.Type = "boolean";
                }
                else if (propertyType == typeof(List<Core.Light>))
                {
                    pluginProperty.Type = "lights";

                    string[] colourClasses = new string[] { "btn-primary", "btn-success", "btn-info", "btn-warning", "btn-danger" };
                    int colourPosition = 0;

                    List<Core.Light> lights = pluginProperty.Value as List<Core.Light>;
                    LightSetup lightSetup = new LightSetup();

                    if (lights != null && lights.Any())
                    {
                        //convert back to 2d array for setup
                        lightSetup.LightRows = new List<LightRow>();

                        int numberOfRows = lights.Max(l => l.Top);
                        int numberOfColumns = lights.Max(l => l.Left);

                        for (int row = 0; row <= numberOfRows; row++)
                        {
                            LightRow lightRow = new LightRow();
                            lightRow.RowIndex = row;
                            lightRow.LightColumns = new List<LightColumn>();
                            for (int column = 0; column <= numberOfColumns; column++)
                            {
                                LightColumn lightColumn = new LightColumn();
                                lightColumn.ColumnIndex = column;
                                if (column == 0 || column == numberOfColumns
                                    || row == 0 || row == numberOfRows)
                                {
                                    
                                    Light light = (from l in lights
                                                  where l.Top == row
                                                      && l.Left == column
                                                  select l).FirstOrDefault();
                                    if (light != null)
                                    {
                                        lightColumn.Id = light.Id.ToString();
                                        lightColumn.Index = light.Index.ToString();

                                        lightColumn.ColourClass = colourClasses[colourPosition++];

                                        lightColumn.Enabled = !string.IsNullOrEmpty(lightColumn.Id);

                                        if (lightColumn.Id == "1")
                                        {
                                            lightSetup.FirstColumnIndex = column;
                                            lightSetup.FirstRowIndex = row;
                                        }
                                    }
                                    else
                                    {
                                        lightColumn.ColourClass = colourClasses[colourPosition++];
                                    }
                                }
                                else
                                {
                                    lightColumn.ColourClass = "disabled";
                                    lightColumn.Enabled = false;
                                }
                                if (colourPosition >= colourClasses.Length)
                                {
                                    colourPosition = 0;
                                }
                                lightRow.LightColumns.Add(lightColumn);
                            }
                            lightSetup.LightRows.Add(lightRow);
                        }
                    }
                    pluginProperty.Value = lightSetup;
                }

                foreach (System.Attribute attr in objectProperty.GetCustomAttributes(true))
                {
                    if ((attr as DisplayAttribute) != null)
                    {
                        DisplayAttribute displayName = (DisplayAttribute)attr;
                        pluginProperty.DisplayName = displayName.Name;
                        pluginProperty.Description = displayName.Description;
                    }
                    else if ((attr as RangeAttribute) != null)
                    {
                        RangeAttribute range = (RangeAttribute)attr;
                        pluginProperty.MinValue = range.Minimum as int?;
                        pluginProperty.MaxValue = range.Maximum as int?;
                    }
                    else if ((attr as RequiredAttribute) != null)
                    {
                        RequiredAttribute required = (RequiredAttribute)attr;
                        pluginProperty.Required = required.AllowEmptyStrings;
                    }
                    else if ((attr as DataMemberAttribute) != null)
                    {
                        dataMember = true;
                    }
                    else if ((attr as KeyAttribute) != null)
                    {
                        exclude = true;
                        break;
                    }
                    else if ((attr as ConfigLookupAttribute) != null)
                    {
                        ConfigLookupAttribute lookup = (ConfigLookupAttribute)attr;
                        pluginProperty.Type = "lookup";

                        PropertyInfo optionsProperty = pluginObjectType.GetProperty(lookup.RetrieveValuesFrom);

                        IEnumerable<object> options = optionsProperty.GetValue(plugin, null) as IEnumerable<object>;
                        List<SelectOption> parsedOptions = new List<SelectOption>();
                        if (options.Any())
                        {
                            foreach (object option in options)
                            {
                                LookupItem lookupItem = option as LookupItem;
                                LookupItemString lookupItemString = option as LookupItemString;
                                SelectOption pluginOption = new SelectOption();

                                if (lookupItem != null)
                                {
                                    pluginOption.Id = lookupItem.Id;
                                    pluginOption.Name = lookupItem.Name;
                                }
                                else if (lookupItemString != null)
                                {
                                    pluginOption.Id = lookupItemString.Id;
                                    pluginOption.Name = lookupItemString.Name;
                                }
                                else
                                {
                                    pluginOption.Id = option;
                                    pluginOption.Name = option.ToString();
                                }
                                parsedOptions.Add(pluginOption);
                            }
                        }
                        pluginProperty.Options = parsedOptions;
                    }
                }

                if (dataMember && !exclude)
                {
                    if (pluginProperty.Type == "lookup" && pluginProperty.Value != null)
                    {
                        var currentValue = (from o in pluginProperty.Options
                                            where o.Id.ToString() == pluginProperty.Value.ToString()
                                            select o).FirstOrDefault();
                        if (currentValue == null)
                        {
                            List<SelectOption> options = pluginProperty.Options as List<SelectOption>;
                            options.Add(new SelectOption()
                            {
                                Id = pluginProperty.Value,
                                Name = "Invalid! " + pluginProperty.Value.ToString()
                            });
                            pluginProperty.Options = options;
                        }
                    }
                    pluginProperties.Add(pluginProperty);
                }
            }

            return pluginProperties.ToArray();
        }