text: /*
   *    Copyright (c) 2019-2021 Grant Erickson
   *    All rights reserved.
   *
   *    Licensed under the Apache License, Version 2.0 (the "License");
   *    you may not use this file except in compliance with the License.
   *    You may obtain a copy of the License at
   *
   *        http://www.apache.org/licenses/LICENSE-2.0
   *
   *    Unless required by applicable law or agreed to in writing,
   *    software distributed under the License is distributed on an "AS
   *    IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
   *    express or implied.  See the License for the specific language
   *    governing permissions and limitations under the License.
   *
   */
  
  /**
   *    @file
   *      This file implements an object for managing the client-side
   *      observation and mutation of a collection of HLX sources.
   *
   */
  
  #include "SourcesController.hpp"
  
  #include <memory>
  
  #include <errno.h>
  #include <inttypes.h>
  #include <limits.h>
  #include <stdlib.h>
  
  #include <LogUtilities/LogUtilities.hpp>
  
  #include <OpenHLX/Client/CommandManager.hpp>
  #include <OpenHLX/Client/SourcesControllerCommands.hpp>
  #include <OpenHLX/Client/SourcesStateChangeNotifications.hpp>
  #include <OpenHLX/Model/SourceModel.hpp>
  #include <OpenHLX/Utilities/Assert.hpp>
  
  
  using namespace HLX::Common;
  using namespace HLX::Model;
  using namespace HLX::Utilities;
  using namespace Nuovations;
  
  
  namespace HLX
  {
  
  namespace Client
  {
  
  /**
   *  @brief
   *    This is the class default constructor.
   *
   */
  SourcesController :: SourcesController(void) :
      Common::SourcesControllerBasis(),
      Client::SourcesControllerBasis(Common::SourcesControllerBasis::mSources,
                                     Common::SourcesControllerBasis::kSourcesMax)
  {
      return;
  }
  
  /**
   *  @brief
   *    This is the class destructor.
   *
   */
  SourcesController :: ~SourcesController(void)
  {
      return;
  }
  
  // MARK: Initializer(s)
  
  /**
   *  @brief
   *    This is the class initializer.
   *
   *  This initializes the class with the specified command manager and
   *  timeout.
   *
   *  @param[in]  aCommandManager  A reference to the command manager
   *                               instance to initialize the controller
   *                               with.
   *  @param[in]  aTimeout         The timeout to initialize the controller
   *                               with that will serve as the timeout for
   *                               future operations with the peer server.
   *
   *  @retval  kStatus_Success              If successful.
   *  @retval  -EINVAL                      If an internal parameter was
   *                                        invalid.
   *  @retval  -ENOMEM                      If memory could not be allocated.
   *  @retval  kError_NotInitialized        The base class was not properly
   *                                        initialized.
   *  @retval  kError_InitializationFailed  If initialization otherwise failed.
   *
   */
  Status
  SourcesController :: Init(CommandManager &aCommandManager, const Timeout &aTimeout)
  {
      DeclareScopedFunctionTracer(lTracer);
      constexpr bool  kRegister = true;
      Status          lRetval = kStatus_Success;
  
  
      lRetval = Common::SourcesControllerBasis::Init();
      nlREQUIRE_SUCCESS(lRetval, done);
  
      lRetval = Client::SourcesControllerBasis::Init(aCommandManager, aTimeout);
      nlREQUIRE_SUCCESS(lRetval, done);
  
      // This MUST come AFTER the base class initialization due to a
      // dependency on the command manager instance.
  
      lRetval = DoNotificationHandlers(kRegister);
      nlREQUIRE_SUCCESS(lRetval, done);
  
  done:
      return (lRetval);
  }
  
  // MARK: Observer Methods
  
  /**
   *  @brief
   *    Get the source model associated with specified source
   *    identifier.
   *
   *  @param[in]   aIdentifier  An immutable reference to the source
   *                            model to obtain.
   *  @param[out]  aModel       A reference to an immutable pointer
   *                            by which to return the source model.
   *
   *  @retval  kStatus_Success  If successful.
   *  @retval  -ERANGE          If the source identifier is smaller
   *                            or larger than supported.
   *
   */
  Status
  SourcesController :: GetSource(const IdentifierType &aIdentifier, const SourceModel *&aModel) const
  {
      Status  lRetval = kStatus_Success;
  
  
      lRetval = ValidateIdentifier(aIdentifier);
      nlREQUIRE_SUCCESS(lRetval, done);
  
      lRetval = mSources.GetSource(aIdentifier, aModel);
      nlREQUIRE_SUCCESS(lRetval, done);
  
  done:
      return (lRetval);
  }
  
  /**
   *  @brief
   *    Get the source identifier with the specified name.
   *
   *  This attempts to lookup the source identifier for the source
   *  with the specified name.
   *
   *  @param[in]   aName                A pointer to a null-terminated
   *                                    C string of the name of the
   *                                    source to find an identifier
   *                                    for.
   *  @param[out]  aSourceIdentifier    A reference to storage by which
   *                                    to return the identifier if
   *                                    successful.
   *
   *  @retval  kStatus_Success  If successful.
   *  @retval  -EINVAL          If @a aName was null.
   *  @retval  -ENOENT          No source could be found with the
   *                            specified name.
   *
   *  @ingroup name
   *
   */
  Status
  SourcesController :: LookupIdentifier(const char *aName, IdentifierType &aSourceIdentifier) const
  {
      const SourceModel * lSourceModel;
      Status              lRetval;
  
  
      lRetval = mSources.GetSource(aName, lSourceModel);
      nlEXPECT_SUCCESS(lRetval, done);
  
      lRetval = lSourceModel->GetIdentifier(aSourceIdentifier);
      nlREQUIRE_SUCCESS(lRetval, done);
  
  done:
      return (lRetval);
  }
  
  // MARK: Mutator Methods
  
  // MARK: Name Mutator Commands
  
  /**
   *  @brief
   *    Set the source to the specified name.
   *
   *  This attempts to set the source with the provided identifier to the
   *  specified name on the peer HLX server controller.
   *
   *  @param[in]  aSourceIdentifier  An immutable reference for the
   *                                 source for which to set the
   *                                 name.
   *  @param[in]  aName              A pointer to the null-terminated
   *                                 C string to set the source name
   *                                 to.
   *
   *  @retval  kStatus_Success  If successful.
   *  @retval  -EINVAL          If @a aName was null.
   *  @retval  -ERANGE          If the source identifier is
   *                            smaller or larger than supported.
   *  @retval  -ENOMEM          If memory could not be allocated
   *                            for the command exchange or
   *                            exchange state.
   *
   *  @ingroup name
   *
   */
  Status
  SourcesController :: SetName(const IdentifierType &aSourceIdentifier,
                               const char *aName)
  {
      Command::ExchangeBasis::MutableCountedPointer lCommand;
      Status                                        lRetval = kStatus_Success;
  
  
      nlREQUIRE_ACTION(aName != nullptr, done, lRetval = -EINVAL);
  
      lRetval = ValidateIdentifier(aSourceIdentifier);
      nlREQUIRE_SUCCESS(lRetval, done);
  
      lCommand.reset(new Command::Sources::SetName());
      nlREQUIRE_ACTION(lCommand, done, lRetval = -ENOMEM);
  
      lRetval = std::static_pointer_cast<Command::Sources::SetName>(lCommand)->Init(aSourceIdentifier, aName);
      nlREQUIRE_SUCCESS(lRetval, done);
  
      lRetval = SendCommand(lCommand,
                            Client::SourcesControllerBasis::SetNameCompleteHandler,
                            Client::SourcesControllerBasis::CommandErrorHandler,
                            static_cast<Client::SourcesControllerBasis *>(this));
      nlREQUIRE_SUCCESS(lRetval, done);
  
   done:
      return (lRetval);
  }
  
  }; // namespace Client
  
  }; // namespace HLX
  