/**
   * (non-javadoc)
   *
   * @see CommunicationsClientConnection#requestListComponentRegistered(PlatformComponentProfile,
   *     DiscoveryQueryParameters)
   */
  @Override
  public void requestListComponentRegistered(
      PlatformComponentProfile networkServiceApplicant,
      DiscoveryQueryParameters discoveryQueryParameters)
      throws CantRequestListException {

    try {

      System.out.println("WsCommunicationsCloudClientConnection - requestListComponentRegistered");

      /*
       * Validate parameter
       */
      if (discoveryQueryParameters == null) {

        throw new IllegalArgumentException(
            "The discoveryQueryParameters is required, can not be null");
      }

      Gson gson = new Gson();
      JsonObject jsonObject = new JsonObject();
      jsonObject.addProperty(
          JsonAttNamesConstants.NETWORK_SERVICE_TYPE,
          networkServiceApplicant.getNetworkServiceType().toString());
      jsonObject.addProperty(
          JsonAttNamesConstants.DISCOVERY_PARAM, discoveryQueryParameters.toJson());

      /*
       * Construct a fermat packet whit the filters
       */
      FermatPacket fermatPacketRespond =
          FermatPacketCommunicationFactory.constructFermatPacketEncryptedAndSinged(
              wsCommunicationsCloudClientChannel.getServerIdentity(), // Destination
              wsCommunicationsCloudClientChannel.getClientIdentity().getPublicKey(), // Sender
              gson.toJson(jsonObject), // Message Content
              FermatPacketType.REQUEST_LIST_COMPONENT_REGISTERED, // Packet type
              wsCommunicationsCloudClientChannel
                  .getClientIdentity()
                  .getPrivateKey()); // Sender private key

      /*
       * Send the encode packet to the server
       */
      wsCommunicationsCloudClientChannel.send(FermatPacketEncoder.encode(fermatPacketRespond));

    } catch (Exception e) {

      CantRequestListException pluginStartException =
          new CantRequestListException(
              CantRequestListException.DEFAULT_MESSAGE,
              e,
              e.getLocalizedMessage(),
              e.getLocalizedMessage());
      throw pluginStartException;
    }
  }
  protected CommunicationNetworkServiceLocal buildCommunicationNetworkServiceLocal(
      final PlatformComponentProfile remoteComponentProfile) {

    return new CommunicationNetworkServiceLocal(
        remoteComponentProfile,
        errorManager,
        eventManager,
        outgoingMessageDao,
        platformComponentProfile.getNetworkServiceType(),
        eventSource);
  }
 protected CommunicationNetworkServiceLocal buildCommunicationNetworkServiceLocal(
     final PlatformComponentProfile remoteComponentProfile) {
   // TODO: Leon tenes que pasarle la instancia del network service plugin root acá
   return new CommunicationNetworkServiceLocal(
       remoteComponentProfile,
       errorManager,
       eventManager,
       outgoingMessageDao,
       platformComponentProfile.getNetworkServiceType(),
       networkServicePluginRoot);
 }
  /**
   * Handles events that indicate a connection to been established between two network services and
   * prepares all objects to work with this new connection
   *
   * @param remoteComponentProfile
   */
  public final void handleEstablishedRequestedNetworkServiceConnection(
      PlatformComponentProfile remoteComponentProfile) {

    try {

      /*
       * Get the active connection
       */
      CommunicationsVPNConnection communicationsVPNConnection =
          communicationsClientConnection.getCommunicationsVPNConnectionStablished(
              platformComponentProfile.getNetworkServiceType(), remoteComponentProfile);

      // Validate the connection
      if (communicationsVPNConnection != null && communicationsVPNConnection.isActive()) {

        /*
         * Instantiate the local reference
         */
        CommunicationNetworkServiceLocal communicationNetworkServiceLocal =
            buildCommunicationNetworkServiceLocal(remoteComponentProfile);

        /*
         * Instantiate the remote reference
         */
        CommunicationNetworkServiceRemoteAgent communicationNetworkServiceRemoteAgent =
            buildCommunicationNetworkServiceRemoteAgent(communicationsVPNConnection);

        /*
         * Register the observer to the observable agent
         */
        communicationNetworkServiceRemoteAgent.addObserver(communicationNetworkServiceLocal);

        /*
         * Start the service thread
         */
        communicationNetworkServiceRemoteAgent.start();

        /*
         * Add to the cache
         */
        communicationNetworkServiceLocalsCache.put(
            remoteComponentProfile.getIdentityPublicKey(), communicationNetworkServiceLocal);
        communicationNetworkServiceRemoteAgentsCache.put(
            remoteComponentProfile.getIdentityPublicKey(), communicationNetworkServiceRemoteAgent);
      }

    } catch (final Exception e) {
      errorManager.reportUnexpectedPluginException(
          pluginVersionReference,
          UnexpectedPluginExceptionSeverity.DISABLES_SOME_FUNCTIONALITY_WITHIN_THIS_PLUGIN,
          e);
    }
  }
  /** Handles the events CompleteComponentRegistrationNotification */
  public void handleCompleteComponentRegistrationNotificationEvent(
      final PlatformComponentProfile platformComponentProfileRegistered) {

    /*
     * If the component registered have my profile and my identity public key
     */
    if (platformComponentProfileRegistered.getPlatformComponentType()
            == PlatformComponentType.NETWORK_SERVICE
        && platformComponentProfileRegistered.getNetworkServiceType()
            == NetworkServiceType.CRYPTO_PAYMENT_REQUEST
        && platformComponentProfileRegistered
            .getIdentityPublicKey()
            .equals(identity.getPublicKey())) {

      /*
       * Mark as register
       */
      this.register = Boolean.TRUE;

      try {

        cryptoPaymentRequestExecutorAgent =
            new CryptoPaymentRequestExecutorAgent(
                this,
                errorManager,
                eventManager,
                cryptoPaymentRequestNetworkServiceDao,
                wsCommunicationsCloudClientManager,
                getPluginVersionReference());

        cryptoPaymentRequestExecutorAgent.start();

      } catch (CantStartAgentException e) {

        CantStartPluginException pluginStartException =
            new CantStartPluginException(e, "", "Problem initializing crypto payment request dao.");
        errorManager.reportUnexpectedPluginException(
            this.getPluginVersionReference(),
            UnexpectedPluginExceptionSeverity.DISABLES_THIS_PLUGIN,
            pluginStartException);
      }
    }
  }
  @Override
  public void beforeRequest(Map<String, List<String>> headers) {

    /*
     * Get json representation
     */
    JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty(
        JsonAttNamesConstants.NETWORK_SERVICE_TYPE,
        remoteParticipantNetworkService.getNetworkServiceType().toString());
    jsonObject.addProperty(
        JsonAttNamesConstants.CLIENT_IDENTITY_VPN, vpnClientIdentity.getPublicKey());
    jsonObject.addProperty(
        JsonAttNamesConstants.APPLICANT_PARTICIPANT_VPN, registerParticipant.toJson());
    jsonObject.addProperty(
        JsonAttNamesConstants.REMOTE_PARTICIPANT_VPN,
        remotePlatformComponentProfile.getIdentityPublicKey());

    /*
     * Add the att to the header
     */
    headers.put(JsonAttNamesConstants.HEADER_ATT_NAME_TI, Arrays.asList(jsonObject.toString()));
    // headers.put("Origin", Arrays.asList("myOrigin"));
  }
  /**
   * Handles events that indicate a connection to been established between two network services and
   * prepares all objects to work with this new connection
   *
   * @param remoteComponentProfile
   */
  public void handleEstablishedRequestedNetworkServiceConnection(
      PlatformComponentProfile remoteComponentProfile) {

    try {

      /*
       * Get the active connection
       */
      CommunicationsVPNConnection communicationsVPNConnection =
          communicationsClientConnection.getCommunicationsVPNConnectionStablished(
              platformComponentProfile.getNetworkServiceType(), remoteComponentProfile);

      // Validate the connection
      if (communicationsVPNConnection != null && communicationsVPNConnection.isActive()) {

        /*
         * Instantiate the local reference
         */
        CommunicationNetworkServiceLocal communicationNetworkServiceLocal =
            new CommunicationNetworkServiceLocal(
                remoteComponentProfile,
                errorManager,
                eventManager,
                outgoingMessageDao,
                platformComponentProfile.getNetworkServiceType());

        /*
         * Instantiate the remote reference
         */
        CommunicationNetworkServiceRemoteAgent communicationNetworkServiceRemoteAgent =
            new CommunicationNetworkServiceRemoteAgent(
                identity,
                communicationsVPNConnection,
                errorManager,
                eventManager,
                incomingMessageDao,
                outgoingMessageDao);

        /*
         * Register the observer to the observable agent
         */
        communicationNetworkServiceRemoteAgent.addObserver(communicationNetworkServiceLocal);

        /*
         * Start the service thread
         */
        communicationNetworkServiceRemoteAgent.start();

        /*
         * Add to the cache
         */
        communicationNetworkServiceLocalsCache.put(
            remoteComponentProfile.getIdentityPublicKey(), communicationNetworkServiceLocal);
        communicationNetworkServiceRemoteAgentsCache.put(
            remoteComponentProfile.getIdentityPublicKey(), communicationNetworkServiceRemoteAgent);
      }

    } catch (Exception e) {
      e.printStackTrace();
      errorManager.reportUnexpectedPluginException(
          Plugins.CHAT_NETWORK_SERVICE,
          UnexpectedPluginExceptionSeverity.DISABLES_SOME_FUNCTIONALITY_WITHIN_THIS_PLUGIN,
          new Exception("Can not get connection"));
    }
  }
  /**
   * (non-javadoc)
   *
   * @see CommunicationsClientConnection#requestVpnConnection(PlatformComponentProfile,
   *     PlatformComponentProfile)
   */
  @Override
  public void requestVpnConnection(
      PlatformComponentProfile applicant, PlatformComponentProfile remoteDestination)
      throws CantEstablishConnectionException {

    try {

      System.out.println("WsCommunicationsCloudClientConnection - requestVpnConnection");

      /*
       * Validate parameter
       */
      if (applicant == null || remoteDestination == null) {

        throw new IllegalArgumentException("All parameters are required, can not be null");
      }

      List<PlatformComponentProfile> participants = new ArrayList();
      participants.add(applicant);
      participants.add(remoteDestination);

      /** Validate all are the same type and NETWORK_SERVICE */
      for (PlatformComponentProfile participant : participants) {

        if (participant.getPlatformComponentType() != PlatformComponentType.NETWORK_SERVICE) {
          throw new IllegalArgumentException(
              "All the PlatformComponentProfile has to be NETWORK_SERVICE ");
        }

        if (participant.getNetworkServiceType() != applicant.getNetworkServiceType()) {
          throw new IllegalArgumentException(
              "All the PlatformComponentProfile has to be the same type of network service type ");
        }
      }

      /*
       * Construct the json object
       */
      Gson gson = new Gson();

      /*
       * Convert to json representation
       */
      String jsonListRepresentation =
          gson.toJson(
              participants,
              new TypeToken<List<PlatformComponentProfileCommunication>>() {}.getType());

      /*
       * Construct a fermat packet whit the request
       */
      FermatPacket fermatPacketRespond =
          FermatPacketCommunicationFactory.constructFermatPacketEncryptedAndSinged(
              wsCommunicationsCloudClientChannel.getServerIdentity(), // Destination
              wsCommunicationsCloudClientChannel.getClientIdentity().getPublicKey(), // Sender
              jsonListRepresentation, // Message Content
              FermatPacketType.COMPONENT_CONNECTION_REQUEST, // Packet type
              wsCommunicationsCloudClientChannel
                  .getClientIdentity()
                  .getPrivateKey()); // Sender private key
      /*
       * Send the encode packet to the server
       */
      wsCommunicationsCloudClientChannel.send(FermatPacketEncoder.encode(fermatPacketRespond));

    } catch (Exception e) {

      CantEstablishConnectionException pluginStartException =
          new CantEstablishConnectionException(
              CantEstablishConnectionException.DEFAULT_MESSAGE,
              e,
              e.getLocalizedMessage(),
              e.getLocalizedMessage());
      throw pluginStartException;
    }
  }
  /** Method tha send a new Message */
  public void sendNewMessage(
      PlatformComponentProfile sender, PlatformComponentProfile destination, String messageContent)
      throws CantSendMessageException {

    try {

      /*
       * ask for a previous connection
       */
      CommunicationNetworkServiceLocal communicationNetworkServiceLocal =
          communicationNetworkServiceConnectionManager.getNetworkServiceLocalInstance(
              destination.getIdentityPublicKey());

      if (communicationNetworkServiceLocal != null) {
        System.out.println(
            "*** 12345 case 7:send msg in NS P2P layer active connection"
                + new Timestamp(System.currentTimeMillis()));
        // Send the message
        communicationNetworkServiceLocal.sendMessage(
            sender.getIdentityPublicKey(),
            sender.getPlatformComponentType(),
            sender.getNetworkServiceType(),
            messageContent);

      } else {
        System.out.println(
            "*** 12345 case 6:send msg in NS P2P layer not active connection"
                + new Timestamp(System.currentTimeMillis()));
        /*
         * Created the message
         */
        FermatMessage fermatMessage =
            FermatMessageCommunicationFactory.constructFermatMessage(
                sender.getIdentityPublicKey(), // Sender
                sender.getPlatformComponentType(), // Sender Type
                sender.getNetworkServiceType(), // Sender NS Type
                destination.getIdentityPublicKey(), // Receiver
                destination.getPlatformComponentType(), // Receiver Type
                destination.getNetworkServiceType(), // Receiver NS Type
                messageContent, // Message Content
                FermatMessageContentType.TEXT // Type
                );

        /*
         * Configure the correct status
         */
        ((FermatMessageCommunication) fermatMessage)
            .setFermatMessagesStatus(FermatMessagesStatus.PENDING_TO_SEND);

        /*
         * Save to the data base table
         */
        communicationNetworkServiceConnectionManager.getOutgoingMessageDao().create(fermatMessage);

        /*
         * Ask the client to connect
         */
        communicationNetworkServiceConnectionManager.connectTo(
            sender, getNetworkServiceProfile(), destination);
      }

    } catch (Exception e) {

      System.out.println("Error sending message: " + e.getMessage());
      throw new CantSendMessageException(CantSendMessageException.DEFAULT_MESSAGE, e);
    }
  }