/**
   * (non-javadoc)
   *
   * @see CommunicationsClientConnection#registerComponentForCommunication(NetworkServiceType,
   *     PlatformComponentProfile)
   */
  @Override
  public void registerComponentForCommunication(
      NetworkServiceType networkServiceNetworkServiceTypeApplicant,
      PlatformComponentProfile platformComponentProfile)
      throws CantRegisterComponentException {

    try {

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

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

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

      Gson gson = new Gson();
      JsonObject jsonObject = new JsonObject();
      jsonObject.addProperty(
          JsonAttNamesConstants.NETWORK_SERVICE_TYPE,
          networkServiceNetworkServiceTypeApplicant.toString());
      jsonObject.addProperty(
          JsonAttNamesConstants.PROFILE_TO_REGISTER, platformComponentProfile.toJson());

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

      String fermatPacketEncode = FermatPacketEncoder.encode(fermatPacket);

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

    } catch (Exception e) {

      CantRegisterComponentException pluginStartException =
          new CantRegisterComponentException(
              CantRegisterComponentException.DEFAULT_MESSAGE,
              e,
              e.getLocalizedMessage(),
              e.getLocalizedMessage());
      throw pluginStartException;
    }
  }
  /**
   * (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;
    }
  }
  /** Register fermat packet processors whit this communication channel */
  private void registerFermatPacketProcessors() {

    /*
     * Clean all
     */
    wsCommunicationsCloudClientChannel.cleanPacketProcessorsRegistered();

    /*
     * Register the packet processors
     */
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new ServerHandshakeRespondPacketProcessor());
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new CompleteRegistrationComponentPacketProcessor());
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new RequestListComponentRegisterPacketProcessor());
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new ComponentConnectionRespondPacketProcessor());
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new CompleteComponentConnectionRequestPacketProcessor());
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new FailureComponentConnectionRequestPacketProcessor());
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new FailureComponentRegistrationRequestPacketProcessor());
    wsCommunicationsCloudClientChannel.registerFermatPacketProcessor(
        new FailureRequestedListNoAvailblePacketProcessor());
  }
  /**
   * (non-javadoc)
   *
   * @see CommunicationsClientConnection#constructBasicPlatformComponentProfileFactory(String,
   *     NetworkServiceType, PlatformComponentType)
   */
  @Override
  public PlatformComponentProfile constructBasicPlatformComponentProfileFactory(
      String identityPublicKey,
      NetworkServiceType networkServiceType,
      PlatformComponentType platformComponentType) {

    try {

      // Validate parameters
      if ((identityPublicKey == null || identityPublicKey == "")
          || networkServiceType == null
          || platformComponentType == null) {

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

      return new PlatformComponentProfileCommunication(
          null,
          wsCommunicationsCloudClientChannel.getClientIdentity().getPublicKey(),
          identityPublicKey,
          null,
          null,
          networkServiceType,
          platformComponentType,
          null);
    } catch (Exception e) {
      throw new IllegalArgumentException(e);
    }
  }
 /**
  * Constructor whit parameters
  *
  * @param uri
  * @param eventManager
  */
 public WsCommunicationsCloudClientConnection(
     URI uri, EventManager eventManager, LocationManager locationManager) {
   super();
   this.wsCommunicationsCloudClientChannel =
       WsCommunicationsCloudClientChannel.constructWsCommunicationsCloudClientFactory(
           uri, new Draft_17(), this, eventManager);
   this.wsCommunicationsCloudClientAgent =
       new WsCommunicationsCloudClientAgent(wsCommunicationsCloudClientChannel);
   this.wsCommunicationsCloudClientPingAgent =
       new WsCommunicationsCloudClientPingAgent(wsCommunicationsCloudClientChannel);
   this.wsCommunicationVPNClientManagerAgent = new WsCommunicationVPNClientManagerAgent();
   this.locationManager = locationManager;
 }
  /**
   * (non-javadoc)
   *
   * @see CommunicationsClientConnection#constructPlatformComponentProfileFactory(String,
   *     String,String, NetworkServiceType, PlatformComponentType, String)
   */
  @Override
  public PlatformComponentProfile constructPlatformComponentProfileFactory(
      String identityPublicKey,
      String alias,
      String name,
      NetworkServiceType networkServiceType,
      PlatformComponentType platformComponentType,
      String extraData) {

    try {

      // Validate parameters
      if ((identityPublicKey == null || identityPublicKey == "")
          || (alias == null || alias == "")
          || (name == null || name == "")
          || networkServiceType == null
          || platformComponentType == null) {

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

      Location location = null;

      try {

        location = locationManager.getLocation();

      } catch (CantGetDeviceLocationException e) {
        System.out.println(
            "WsCommunicationsCloudClientConnection - Error getting the geolocation for this device ");
      }

      /*
       * Construct a PlatformComponentProfile instance
       */
      return new PlatformComponentProfileCommunication(
          alias,
          wsCommunicationsCloudClientChannel.getClientIdentity().getPublicKey(),
          identityPublicKey,
          location,
          name,
          networkServiceType,
          platformComponentType,
          extraData);

    } catch (Exception e) {
      throw new IllegalArgumentException(e);
    }
  }
 /**
  * (non-javadoc)
  *
  * @see CommunicationsClientConnection#isRegister()
  */
 public boolean isRegister() {
   return wsCommunicationsCloudClientChannel.isRegister();
 }
 /**
  * (non-javadoc)
  *
  * @see CommunicationsClientConnection#isConnected()
  */
 @Override
 public boolean isConnected() {
   return wsCommunicationsCloudClientChannel.getConnection().isOpen();
 }
  /**
   * (non-javadoc)
   *
   * @see CommunicationsClientConnection#requestDiscoveryVpnConnection(PlatformComponentProfile,
   *     PlatformComponentProfile, PlatformComponentProfile)
   */
  @Override
  public void requestDiscoveryVpnConnection(
      PlatformComponentProfile applicantParticipant,
      PlatformComponentProfile applicantNetworkService,
      PlatformComponentProfile remoteParticipant)
      throws CantEstablishConnectionException {

    try {

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

      /*
       * Validate parameter
       */
      if (applicantParticipant == null
          || applicantNetworkService == null
          || remoteParticipant == null) {

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

      /*
       * Validate are the  type NETWORK_SERVICE
       */
      if (applicantNetworkService.getPlatformComponentType()
          != PlatformComponentType.NETWORK_SERVICE) {
        throw new IllegalArgumentException(
            "All the PlatformComponentProfile has to be NETWORK_SERVICE ");
      }

      /*
       * Construct the json object
       */
      Gson gson = new Gson();
      JsonObject packetContent = new JsonObject();
      packetContent.addProperty(
          JsonAttNamesConstants.APPLICANT_PARTICIPANT_VPN, applicantParticipant.toJson());
      packetContent.addProperty(
          JsonAttNamesConstants.APPLICANT_PARTICIPANT_NS_VPN, applicantNetworkService.toJson());
      packetContent.addProperty(
          JsonAttNamesConstants.REMOTE_PARTICIPANT_VPN, remoteParticipant.toJson());

      /*
       * Convert to json representation
       */
      String packetContentJson = gson.toJson(packetContent);

      /*
       * Construct a fermat packet whit the request
       */
      FermatPacket fermatPacketRespond =
          FermatPacketCommunicationFactory.constructFermatPacketEncryptedAndSinged(
              wsCommunicationsCloudClientChannel.getServerIdentity(), // Destination
              wsCommunicationsCloudClientChannel.getClientIdentity().getPublicKey(), // Sender
              packetContentJson, // Message Content
              FermatPacketType.DISCOVERY_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;
    }
  }
  /**
   * (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 that request to the communication cloud server the list of component registered that
   * match whit the discovery query params
   *
   * @param discoveryQueryParameters
   * @throws CantRequestListException this exception means the list receive is empty or a internal
   *     error
   */
  public List<PlatformComponentProfile> requestListComponentRegisteredSocket(
      DiscoveryQueryParameters discoveryQueryParameters) throws CantRequestListException {

    System.out.println(
        "WsCommunicationsCloudClientConnection - new requestListComponentRegistered");
    List<PlatformComponentProfile> resultList = new ArrayList<>();
    Socket clientConnect = null;
    BufferedReader bufferedReader = null;
    PrintWriter printWriter = null;

    try {

      /*
       * Validate parameter
       */
      if (discoveryQueryParameters == null) {
        throw new IllegalArgumentException(
            "The discoveryQueryParameters is required, can not be null");
      }

      /*
       * Construct a jsonObject whit the parameters
       */
      Gson gson = new Gson();
      JsonObject jsonObject = new JsonObject();
      jsonObject.addProperty(
          JsonAttNamesConstants.NAME_IDENTITY,
          wsCommunicationsCloudClientChannel.getIdentityPublicKey());
      jsonObject.addProperty(
          JsonAttNamesConstants.DISCOVERY_PARAM, discoveryQueryParameters.toJson());

      clientConnect = new Socket(WsCommunicationsCloudClientPluginRoot.SERVER_IP, 9001);
      bufferedReader = new BufferedReader(new InputStreamReader(clientConnect.getInputStream()));

      printWriter = new PrintWriter(clientConnect.getOutputStream());
      printWriter.println(gson.toJson(jsonObject));
      printWriter.flush();

      String respondServer = bufferedReader.readLine();

      if (respondServer != null
          && respondServer != ""
          && respondServer.contains(JsonAttNamesConstants.RESULT_LIST)) {

        /*
         * Decode into a json object
         */
        JsonParser parser = new JsonParser();
        JsonObject respondJsonObject = (JsonObject) parser.parse(respondServer);

        /*
         * Get the receivedList
         */
        resultList =
            gson.fromJson(
                respondJsonObject.get(JsonAttNamesConstants.RESULT_LIST).getAsString(),
                new TypeToken<List<PlatformComponentProfileCommunication>>() {}.getType());

        System.out.println(
            "WsCommunicationsCloudClientConnection - resultList.size() = " + resultList.size());
      }

      bufferedReader.close();
      printWriter.close();
      clientConnect.close();

    } catch (Exception e) {

      try {

        if (clientConnect != null) {
          bufferedReader.close();
          printWriter.close();
          clientConnect.close();
        }

      } catch (Exception ex) {
      }

      e.printStackTrace();
      CantRequestListException cantRequestListException =
          new CantRequestListException(
              CantRequestListException.DEFAULT_MESSAGE,
              e,
              e.getLocalizedMessage(),
              e.getLocalizedMessage());
      throw cantRequestListException;
    }

    return resultList;
  }
  /**
   * (non-javadoc)
   *
   * @see CommunicationsClientConnection#requestListComponentRegistered(DiscoveryQueryParameters)
   */
  @Override
  public List<PlatformComponentProfile> requestListComponentRegistered(
      DiscoveryQueryParameters discoveryQueryParameters) throws CantRequestListException {

    System.out.println(
        "WsCommunicationsCloudClientConnection - new requestListComponentRegistered");
    List<PlatformComponentProfile> resultList = new ArrayList<>();

    try {

      /*
       * Validate parameter
       */
      if (discoveryQueryParameters == null) {
        throw new IllegalArgumentException(
            "The discoveryQueryParameters is required, can not be null");
      }

      /*
       * Construct a jsonObject whit the parameters
       */
      Gson gson = new Gson();
      JsonObject jsonObject = new JsonObject();
      jsonObject.addProperty(
          JsonAttNamesConstants.NAME_IDENTITY,
          wsCommunicationsCloudClientChannel.getIdentityPublicKey());
      jsonObject.addProperty(
          JsonAttNamesConstants.DISCOVERY_PARAM, discoveryQueryParameters.toJson());

      // Create a new RestTemplate instance
      HttpHeaders requestHeaders = new HttpHeaders();
      requestHeaders.set("Connection", "Close");
      requestHeaders.setAccept(
          Collections.singletonList(new org.springframework.http.MediaType("application", "json")));

      HttpEntity<?> requestEntity = new HttpEntity<Object>(jsonObject.toString(), requestHeaders);
      RestTemplate restTemplate = new RestTemplate();
      restTemplate
          .getMessageConverters()
          .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));

      ResponseEntity<String> responseEntity =
          restTemplate.exchange(WEB_SERVICE_URL, HttpMethod.POST, requestEntity, String.class);

      String respond = responseEntity.getBody();
      // System.out.println("responseEntity = " + respond);

      /*
       * if respond have the result list
       */
      if (respond.contains(JsonAttNamesConstants.RESULT_LIST)) {

        /*
         * Decode into a json object
         */
        JsonParser parser = new JsonParser();
        JsonObject respondJsonObject = (JsonObject) parser.parse(respond.toString());

        /*
         * Get the receivedList
         */
        resultList =
            gson.fromJson(
                respondJsonObject.get(JsonAttNamesConstants.RESULT_LIST).getAsString(),
                new TypeToken<List<PlatformComponentProfileCommunication>>() {}.getType());

        System.out.println(
            "WsCommunicationsCloudClientConnection - resultList.size() = " + resultList.size());

      } else {
        System.out.println(
            "WsCommunicationsCloudClientConnection - Requested list is not available, resultList.size() = "
                + resultList.size());
      }

    } catch (Exception e) {
      e.printStackTrace();
      CantRequestListException cantRequestListException =
          new CantRequestListException(
              CantRequestListException.DEFAULT_MESSAGE,
              e,
              e.getLocalizedMessage(),
              e.getLocalizedMessage());
      throw cantRequestListException;
    }

    return resultList;
  }