/// <summary>
        /// Update the specified connection.
        /// </summary>
        /// <param name="connection">An instance with the updated data.</param>
        public void Update(ControlModuleConnection connection)
        {
            string sql = string.Empty;

            Logger.LogDebug(this, "[CLASS].Update([{0}])", connection);

            try
            {
                // Check if related decoder exists
                CheckDecoderExists(connection);

                Connect();

                sql = @"UPDATE 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" 
                    SET 
                        [index]    = @index,
                        decoderid  = @decoderid, 
                        blockid    = @blockid, 
                        name       = @name, 
                        address    = @address, 
                        output     = @output, 
                        switchtime = @switchtime, 
                        out1       = @out1, 
                        out2       = @out2
                    WHERE 
                        id = @id";

                SetParameter("index", connection.Index);
                SetParameter("decoderid", connection.DecoderID);
                SetParameter("blockid", connection.ElementID);
                SetParameter("name", connection.Name);
                SetParameter("address", connection.Address);
                SetParameter("output", connection.Output);
                SetParameter("switchtime", connection.SwitchTime);
                SetParameter("out1", connection.OutputMap.Map);
                SetParameter("out2", connection.Output2);
                SetParameter("id", connection.ID);

                ExecuteNonQuery(sql);
            }
            catch (Exception ex)
            {
                Logger.LogError(this, ex);

                throw;
            }
            finally
            {
                Disconnect();
            }
        }
        /// <summary>
        /// Adds a new output to an existing decoder.
        /// </summary>
        /// <param name="connection">An instance of <see cref="ControlModuleConnection"/> containing the data for the new connection.</param>
        public void Add(ControlModuleConnection connection)
        {
            string sql = string.Empty;

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

            try
            {
                // Check if related module exists
                CheckDecoderExists(connection);

                Connect();

                // Añade el registro
                sql = @"INSERT INTO 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" (" + ControlModuleConnectionManager.SQL_FIELDS_INSERT + @") 
                    VALUES 
                        (@index, @decoderid, @blockid, @name, @address, @output, @switchtime, @out1, @out2)";

                SetParameter("index", connection.Index);
                SetParameter("decoderid", connection.DecoderID);
                SetParameter("blockid", connection.ElementID);
                SetParameter("name", connection.Name);
                SetParameter("address", connection.Address);
                SetParameter("output", connection.Output);
                SetParameter("switchtime", connection.SwitchTime);
                SetParameter("out1", connection.OutputMap.Map);
                SetParameter("out2", connection.Output2);

                ExecuteNonQuery(sql);

                // Obtiene el nuevo ID
                sql = @"SELECT 
                        Max(id) As id 
                    FROM 
                        " + ControlModuleConnectionManager.SQL_TABLE;

                connection.ID = (int)ExecuteScalar(sql);
            }
            catch (Exception ex)
            {
                Logger.LogError(this, ex);

                throw;
            }
            finally
            {
                Disconnect();
            }
        }
        private void CheckDecoderExists(ControlModuleConnection output)
        {
            // Check if the decoder is informed
            if (output.DecoderID <= 0)
            {
                throw new LayoutConfigurationException("Cannot create a decoder output without related decoder.");
            }

            // Check if the decoder is in database
            ControlModuleManager decManager = new ControlModuleManager(this.Settings);

            if (decManager.GetByID(output.DecoderID) == null)
            {
                throw new LayoutConfigurationException("Cannot create a decoder output: related decoder #{0} not found.", output.DecoderID);
            }
        }
        /// <summary>
        /// Read a category from the current reader record.
        /// </summary>
        internal static ControlModuleConnection ReadEntityRecord(SQLiteDataReader reader)
        {
            ControlModuleConnection record = new ControlModuleConnection();

            record.ID         = reader.GetInt32(0);
            record.Index      = reader.GetInt32(1);
            record.DecoderID  = reader.GetInt32(2);
            record.ElementID  = reader.IsDBNull(3) ? 0 : reader.GetInt32(3);
            record.Name       = reader.IsDBNull(4) ? string.Empty : reader.GetString(4);
            record.Address    = reader.IsDBNull(5) ? 0 : reader.GetInt32(5);
            record.Output     = reader.IsDBNull(6) ? 0 : reader.GetInt32(6);
            record.SwitchTime = reader.IsDBNull(7) ? 0 : reader.GetInt32(7);
            record.OutputMap  = new ConnectionMap(reader.IsDBNull(8) ? 0 : reader.GetInt32(8));
            record.Output2    = reader.IsDBNull(9) ? ControlModuleConnection.DecoderFunctionOutputStatus.Unknown : (ControlModuleConnection.DecoderFunctionOutputStatus)reader.GetInt32(9);

            return(record);
        }
        /// <summary>
        /// Update the specified connection.
        /// </summary>
        /// <param name="connection">An instance with the updated data.</param>
        public void SetConnectionMap(ControlModuleConnection connection)
        {
            string sql = string.Empty;

            Logger.LogDebug(this, "[CLASS].SetConnectionMap([{0}])", connection);

            try
            {
                // Check if related decoder exists
                CheckDecoderExists(connection);

                Connect();

                sql = @"UPDATE 
                        " + ControlModuleConnectionManager.SQL_TABLE + @" 
                    SET 
                        out1 = @out1
                    WHERE 
                        id = @id";

                SetParameter("out1", connection.OutputMap.Map);
                SetParameter("id", connection.ID);

                ExecuteNonQuery(sql);
            }
            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();
            }
        }