/// <summary>
        /// Get the requestes connection.
        /// </summary>
        /// <param name="id">Connection unique identifier (DB).</param>
        /// <returns>The requested instance of <see cref="ControlModuleConnection"/> or <c>null</c> if the connection cannot be found.</returns>
        public ControlModuleConnection GetByID(Int64 id)
        {
            string sql = string.Empty;

            Logger.LogDebug(this, "[CLASS].GetByID({0})", id);

            try
            {
                Connect();

                sql = @"SELECT 
                        " + ControlModuleConnectionManager.SQL_FIELDS_SELECT + @" 
                    FROM 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" 
                    WHERE 
                        id = @id";

                SetParameter("id", id);

                using (SQLiteDataReader reader = ExecuteReader(sql))
                {
                    if (reader.Read())
                    {
                        return(ControlModuleConnectionManager.ReadEntityRecord(reader));
                    }
                }

                return(null);
            }
            catch (Exception ex)
            {
                Logger.LogError(this, ex);

                throw;
            }
            finally
            {
                Disconnect();
            }
        }
        /// <summary>
        /// Gets all connections using the same digital address.
        /// </summary>
        /// <param name="address">Digital address.</param>
        /// <returns>The requested list of <see cref="ControlModuleConnection"/> related to the specified address.</returns>
        public List <ControlModuleConnection> GetDuplicated(int address)
        {
            string sql = string.Empty;
            ControlModuleConnection        item     = null;
            List <long>                    repeated = new List <long>();
            List <ControlModuleConnection> items    = new List <ControlModuleConnection>();

            Logger.LogDebug(this, "[CLASS].GetDuplicated({0})", address);

            try
            {
                Connect();

                // Get repeated addresses
                sql = @"SELECT 
                        address, 
                        COUNT(*) c 
                    FROM 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" 
                    GROUP BY 
                        address 
                    HAVING 
                        c > 1 And
                        address = @address;";

                SetParameter("address", address);

                using (SQLiteDataReader reader = ExecuteReader(sql))
                {
                    while (reader.Read())
                    {
                        repeated.Add(reader.GetInt64(0));
                    }
                }

                // Get connections with repeated addresses
                sql = @"SELECT 
                        " + ControlModuleConnectionManager.SQL_FIELDS_SELECT + @" 
                    FROM 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" 
                    WHERE 
                        address = @address 
                    ORDER BY 
                        id";

                SetParameter("address", address);

                using (SQLiteDataReader reader = ExecuteReader(sql))
                {
                    while (reader.Read())
                    {
                        item = ControlModuleConnectionManager.ReadEntityRecord(reader);
                        if (item != null)
                        {
                            items.Add(item);
                        }
                    }
                }

                return(items);
            }
            catch (Exception ex)
            {
                Logger.LogError(this, ex);

                throw;
            }
            finally
            {
                Disconnect();
            }
        }
        /// <summary>
        /// Gets connections of the specified type for the specified element.
        /// </summary>
        /// <param name="element">Element.</param>
        /// <param name="type">Type of element.</param>
        /// <returns>The requested list of <see cref="ControlModuleConnection"/> related to the specified element.</returns>
        public ControlModuleConnection[] GetByElement(ElementBase element, ControlModule.ModuleType type)
        {
            string sql = string.Empty;
            ControlModuleConnection item = null;

            ControlModuleConnection[] items = null;

            Logger.LogDebug(this,
                            "[CLASS].GetByElement([{0}], {1})",
                            (element != null ? element.ID.ToString() : "null"), type);

            // Return an empty array if element is null or doesn't have outputs
            if (element == null)
            {
                return(new ControlModuleConnection[0]);
            }
            else if (type == ControlModule.ModuleType.Accessory && (element.AccessoryConnections == null || element.AccessoryConnections.Length <= 0))
            {
                return(new ControlModuleConnection[0]);
            }
            else if (type == ControlModule.ModuleType.Sensor && (element.FeedbackConnections == null || element.FeedbackConnections.Length <= 0))
            {
                return(new ControlModuleConnection[0]);
            }

            try
            {
                switch (type)
                {
                case ControlModule.ModuleType.Accessory:
                    items = new ControlModuleConnection[element.AccessoryConnections.Length];
                    break;

                case ControlModule.ModuleType.Sensor:
                    items = new ControlModuleConnection[element.FeedbackConnections.Length];
                    break;
                }

                Connect();

                sql = @"SELECT 
                        " + ControlModuleConnectionManager.SQL_FIELDS_SELECT + @" 
                    FROM 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" con 
                    WHERE 
                        blockid = @blockid And 
                        @type   = (SELECT type 
                                   FROM   " + ControlModuleManager.SQL_TABLE + @" deco 
                                   WHERE  con.decoderid = deco.id) 
                    ORDER BY 
                        [index] Asc,
                        id      Asc";

                SetParameter("blockid", element.ID);
                SetParameter("type", (int)type);

                using (SQLiteDataReader reader = ExecuteReader(sql))
                {
                    while (reader.Read())
                    {
                        item = ControlModuleConnectionManager.ReadEntityRecord(reader);
                        if (item != null && item.Index <= items.Length)
                        {
                            items[item.Index - 1] = item;
                        }
                    }
                }

                return(items);
            }
            catch (Exception ex)
            {
                Logger.LogError(this, ex);

                throw;
            }
            finally
            {
                Disconnect();
            }
        }
        /// <summary>
        /// Gets all blocks from a specified switchboard panel.
        /// </summary>
        /// <param name="decoderId">The switchboard panel unique identifier (DB).</param>
        /// <returns>The requested list of <see cref="ElementBase"/>.</returns>
        public List <ControlModuleConnection> GetByDecoder(int decoderId)
        {
            string                         sql    = string.Empty;
            ControlModule                  module = null;
            ControlModuleConnection        item   = null;
            List <ControlModuleConnection> items  = new List <ControlModuleConnection>();

            Logger.LogDebug(this, "[CLASS].GetByDecoder({0})", decoderId);

            try
            {
                Connect();

                sql = @"SELECT 
                        " + ControlModuleManager.SQL_FIELDS_SELECT + @" 
                    FROM 
                        " + ControlModuleManager.SQL_TABLE + @" 
                    WHERE 
                        id = @id";

                SetParameter("id", decoderId);

                using (SQLiteDataReader reader = ExecuteReader(sql))
                {
                    if (reader.Read())
                    {
                        module = ControlModuleManager.ReadEntityRecord(reader);
                    }
                }

                if (module == null)
                {
                    return(items);
                }

                sql = @"SELECT 
                        " + ControlModuleConnectionManager.SQL_FIELDS_SELECT + @" 
                    FROM 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" 
                    WHERE 
                        decoderid = @decoderid 
                    ORDER BY 
                        name";

                SetParameter("decoderid", decoderId);

                using (SQLiteDataReader reader = ExecuteReader(sql))
                {
                    while (reader.Read())
                    {
                        item = ControlModuleConnectionManager.ReadEntityRecord(reader);
                        if (item != null)
                        {
                            items.Add(item);
                        }
                    }
                }

                return(items);
            }
            catch (Exception ex)
            {
                Logger.LogError(this, ex);

                throw;
            }
            finally
            {
                Disconnect();
            }
        }
        /// <summary>
        /// Adds a new module into the current project.
        /// </summary>
        /// <param name="module">An instance of <see cref="ControlModule"/> containing the data.</param>
        public void Add(ControlModule module)
        {
            int    addr = 0;
            string sql  = string.Empty;
            ControlModuleConnectionManager connManager = null;

            Logger.LogDebug(this, "[CLASS].Add([{0}])", module);

            try
            {
                Connect();

                // Adds the new decoder
                sql = @"INSERT INTO 
                        " + ControlModuleManager.SQL_TABLE + @" (" + ControlModuleManager.SQL_FIELDS_INSERT + @") 
                    VALUES 
                        (@name, @manufacturer, @model, @outputs, @startaddress, @type, @description)";

                SetParameter("name", module.Name);
                SetParameter("manufacturer", module.Manufacturer);
                SetParameter("model", module.Model);
                SetParameter("outputs", module.Outputs);
                SetParameter("startaddress", module.StartAddress);
                SetParameter("type", module.Type);
                SetParameter("description", module.Notes);

                ExecuteNonQuery(sql);

                // Gets the generated new ID
                sql = @"SELECT 
                        Max(id) As id 
                    FROM 
                        " + ControlModuleManager.SQL_TABLE;

                module.ID = (int)ExecuteScalar(sql);

                Disconnect();

                // Initialize the address for the sensor module
                addr = module.StartAddress;

                // Generate dummy connections with appropriate name
                connManager = new ControlModuleConnectionManager(this.Settings);
                for (int i = 1; i <= module.Outputs; i++)
                {
                    switch (module.Type)
                    {
                    case ControlModule.ModuleType.Accessory:
                        connManager.Add(new ControlModuleConnection(i.ToString(), module));
                        break;

                    case ControlModule.ModuleType.Sensor:
                        connManager.Add(new ControlModuleConnection(i.ToString(), module, addr, i));
                        break;
                    }

                    // Update address by sensor output group
                    if (i % 4 == 0)
                    {
                        addr++;
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(this, ex);

                throw;
            }
            finally
            {
                Disconnect();
            }
        }