content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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.
   */
  package org.apache.camel.component.digitalocean.producer;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import com.myjeeva.digitalocean.common.ResourceType;
  import com.myjeeva.digitalocean.exception.DigitalOceanException;
  import com.myjeeva.digitalocean.exception.RequestUnsuccessfulException;
  import com.myjeeva.digitalocean.pojo.Action;
  import com.myjeeva.digitalocean.pojo.Actions;
  import com.myjeeva.digitalocean.pojo.Backups;
  import com.myjeeva.digitalocean.pojo.Delete;
  import com.myjeeva.digitalocean.pojo.Droplet;
  import com.myjeeva.digitalocean.pojo.Droplets;
  import com.myjeeva.digitalocean.pojo.Image;
  import com.myjeeva.digitalocean.pojo.Kernels;
  import com.myjeeva.digitalocean.pojo.Key;
  import com.myjeeva.digitalocean.pojo.Neighbors;
  import com.myjeeva.digitalocean.pojo.Region;
  import com.myjeeva.digitalocean.pojo.Resource;
  import com.myjeeva.digitalocean.pojo.Response;
  import com.myjeeva.digitalocean.pojo.Snapshots;
  import org.apache.camel.Exchange;
  import org.apache.camel.Message;
  import org.apache.camel.component.digitalocean.DigitalOceanConfiguration;
  import org.apache.camel.component.digitalocean.DigitalOceanEndpoint;
  import org.apache.camel.component.digitalocean.constants.DigitalOceanHeaders;
  import org.apache.camel.component.digitalocean.constants.DigitalOceanOperations;
  import org.apache.camel.util.ObjectHelper;
  
  /**
   * The DigitalOcean producer for Droplets API.
   */
  public class DigitalOceanDropletsProducer extends DigitalOceanProducer {
  
      private Integer dropletId;
  
      public DigitalOceanDropletsProducer(DigitalOceanEndpoint endpoint, DigitalOceanConfiguration configuration) {
          super(endpoint, configuration);
      }
  
      @Override
      public void process(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
  
          DigitalOceanOperations op = determineOperation(exchange);
          if (op != DigitalOceanOperations.create && op != DigitalOceanOperations.list
                  && op != DigitalOceanOperations.listAllNeighbors) {
              dropletId = exchange.getIn().getHeader(DigitalOceanHeaders.ID, Integer.class);
              if (ObjectHelper.isEmpty(dropletId)) {
                  throw new IllegalArgumentException(DigitalOceanHeaders.ID + " must be specified");
              }
  
          }
  
          switch (op) {
              case create:
                  createDroplet(exchange);
                  break;
              case list:
                  getDroplets(exchange);
                  break;
              case delete:
                  deleteDroplet(exchange);
                  break;
              case get:
                  getDroplet(exchange);
                  break;
              case listActions:
                  getDropletActions(exchange);
                  break;
              case listSnapshots:
                  getDropletSnapshots(exchange);
                  break;
              case listKernels:
                  getDropletKernels(exchange);
                  break;
              case listBackups:
                  getDropletBackups(exchange);
                  break;
              case listNeighbors:
                  getDropletNeighbors(exchange);
                  break;
              case listAllNeighbors:
                  getAllDropletNeighbors(exchange);
                  break;
              case enableBackups:
                  enableDropletBackups(exchange);
                  break;
              case disableBackups:
                  disableDropletBackups(exchange);
                  break;
              case reboot:
                  rebootDroplet(exchange);
                  break;
              case powerCycle:
                  powerCycleDroplet(exchange);
                  break;
              case shutdown:
                  shutdownDroplet(exchange);
                  break;
              case powerOn:
                  powerOnDroplet(exchange);
                  break;
              case powerOff:
                  powerOffDroplet(exchange);
                  break;
              case restore:
                  restoreDroplet(exchange);
                  break;
              case resetPassword:
                  resetDropletPassword(exchange);
                  break;
              case resize:
                  resizeDroplet(exchange);
                  break;
              case rebuild:
                  rebuildDroplet(exchange);
                  break;
              case rename:
                  renameDroplet(exchange);
                  break;
              case changeKernel:
                  changeDropletKernel(exchange);
                  break;
              case enableIpv6:
                  enableDropletIpv6(exchange);
                  break;
              case enablePrivateNetworking:
                  enableDropletPrivateNetworking(exchange);
                  break;
              case takeSnapshot:
                  takeDropletSnapshot(exchange);
                  break;
              case tag:
                  tagDroplet(exchange);
                  break;
              case untag:
                  untagDroplet(exchange);
                  break;
              default:
                  throw new IllegalArgumentException("Unsupported operation");
          }
      }
  
      private void getDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Droplet droplet = getEndpoint().getDigitalOceanClient().getDropletInfo(dropletId);
          LOG.trace("Droplet {}", droplet);
          exchange.getMessage().setBody(droplet);
      }
  
      private void getDroplets(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Droplets droplets = getEndpoint().getDigitalOceanClient().getAvailableDroplets(configuration.getPage(),
                  configuration.getPerPage());
          LOG.trace("All Droplets : page {} / {} per page [{}] ", configuration.getPage(), configuration.getPerPage(),
                  droplets.getDroplets());
          exchange.getMessage().setBody(droplets.getDroplets());
      }
  
      private void getDropletActions(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Actions actions = getEndpoint().getDigitalOceanClient().getAvailableDropletActions(dropletId, configuration.getPage(),
                  configuration.getPerPage());
          LOG.trace("Actions for Droplet {} : page {} / {} per page [{}] ", dropletId, configuration.getPage(),
                  configuration.getPerPage(), actions.getActions());
          exchange.getMessage().setBody(actions.getActions());
      }
  
      private void getDropletKernels(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Kernels kernels = getEndpoint().getDigitalOceanClient().getDropletKernels(dropletId, configuration.getPage(),
                  configuration.getPerPage());
          LOG.trace("Kernels for Droplet {} : page {} / {} per page [{}] ", dropletId, configuration.getPage(),
                  configuration.getPerPage(), kernels.getKernels());
          exchange.getMessage().setBody(kernels.getKernels());
      }
  
      private void getDropletBackups(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Backups backups = getEndpoint().getDigitalOceanClient().getDropletBackups(dropletId, configuration.getPage(),
                  configuration.getPerPage());
          LOG.trace("Backups for Droplet {} : page {} / {} per page [{}] ", dropletId, configuration.getPage(),
                  configuration.getPerPage(), backups.getBackups());
          exchange.getMessage().setBody(backups.getBackups());
      }
  
      private void getDropletSnapshots(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Snapshots snapshots = getEndpoint().getDigitalOceanClient().getDropletSnapshots(dropletId, configuration.getPage(),
                  configuration.getPerPage());
          LOG.trace("Snapshots for Droplet {} : page {} / {} per page [{}] ", dropletId, configuration.getPage(),
                  configuration.getPerPage(), snapshots.getSnapshots());
          exchange.getMessage().setBody(snapshots.getSnapshots());
      }
  
      private void getDropletNeighbors(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Droplets droplets = getEndpoint().getDigitalOceanClient().getDropletNeighbors(dropletId, configuration.getPage());
          LOG.trace("Neighbors for Droplet {} : page {} [{}] ", dropletId, configuration.getPage(), droplets.getDroplets());
          exchange.getMessage().setBody(droplets.getDroplets());
      }
  
      private void getAllDropletNeighbors(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Neighbors neighbors = getEndpoint().getDigitalOceanClient().getAllDropletNeighbors(configuration.getPage());
          LOG.trace("All Neighbors : page {} [{}] ", configuration.getPage(), neighbors.getNeighbors());
          exchange.getMessage().setBody(neighbors.getNeighbors());
      }
  
      private void deleteDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Delete delete = getEndpoint().getDigitalOceanClient().deleteDroplet(dropletId);
          LOG.trace("Delete Droplet {}", delete);
          exchange.getMessage().setBody(delete);
      }
  
      @SuppressWarnings("unchecked")
      private void createDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Message in = exchange.getIn();
  
          Droplet droplet = new Droplet();
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.REGION))) {
              droplet.setRegion(new Region(in.getHeader(DigitalOceanHeaders.REGION, String.class)));
          } else {
              throw new IllegalArgumentException(DigitalOceanHeaders.REGION + " must be specified");
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_SIZE))) {
              droplet.setSize(in.getHeader(DigitalOceanHeaders.DROPLET_SIZE, String.class));
          } else {
              throw new IllegalArgumentException(DigitalOceanHeaders.DROPLET_SIZE + " must be specified");
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_IMAGE))) {
              droplet.setImage(new Image(in.getHeader(DigitalOceanHeaders.DROPLET_IMAGE, String.class)));
          } else {
              throw new IllegalArgumentException(DigitalOceanHeaders.DROPLET_IMAGE + " must be specified");
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_KEYS))) {
              List<String> keys = (List<String>) exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_KEYS);
              droplet.setKeys(keys.stream().map(Key::new).toList());
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_ENABLE_BACKUPS))) {
              droplet.setEnableBackup(in.getHeader(DigitalOceanHeaders.DROPLET_ENABLE_BACKUPS, Boolean.class));
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_ENABLE_IPV6))) {
              droplet.setEnableIpv6(in.getHeader(DigitalOceanHeaders.DROPLET_ENABLE_IPV6, Boolean.class));
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_ENABLE_PRIVATE_NETWORKING))) {
              droplet.setEnablePrivateNetworking(
                      in.getHeader(DigitalOceanHeaders.DROPLET_ENABLE_PRIVATE_NETWORKING, Boolean.class));
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_USER_DATA))) {
              droplet.setUserData(in.getHeader(DigitalOceanHeaders.DROPLET_USER_DATA, String.class));
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_VOLUMES))) {
              droplet.setVolumeIds((List<String>) exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_VOLUMES));
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_TAGS))) {
              droplet.setTags((List<String>) exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_TAGS));
          }
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.NAMES))) {
              droplet.setNames((List<String>) in.getHeader(DigitalOceanHeaders.NAMES));
              Droplets droplets = getEndpoint().getDigitalOceanClient().createDroplets(droplet);
              LOG.trace("Droplets created {}", droplets);
              exchange.getMessage().setBody(droplets.getDroplets());
          } else if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.NAME))) {
              droplet.setName(in.getHeader(DigitalOceanHeaders.NAME, String.class));
              droplet = getEndpoint().getDigitalOceanClient().createDroplet(droplet);
              LOG.trace("Droplet created {}", droplet);
              exchange.getMessage().setBody(droplet);
          } else {
              throw new IllegalArgumentException(
                      DigitalOceanHeaders.NAMES + " or " + DigitalOceanHeaders.NAME + " must be specified");
          }
  
      }
  
      private void restoreDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          if (ObjectHelper.isEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.IMAGE_ID))) {
              throw new IllegalArgumentException(DigitalOceanHeaders.IMAGE_ID + " must be specified");
          }
  
          Action action = getEndpoint().getDigitalOceanClient().restoreDroplet(dropletId,
                  exchange.getIn().getHeader(DigitalOceanHeaders.IMAGE_ID, Integer.class));
          LOG.trace("DropletAction Restore [{}] ", action);
          exchange.getMessage().setBody(action);
  
      }
  
      private void resizeDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          if (ObjectHelper.isEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_SIZE))) {
              throw new IllegalArgumentException(DigitalOceanHeaders.DROPLET_SIZE + " must be specified");
          }
  
          Action action = getEndpoint().getDigitalOceanClient().resizeDroplet(dropletId,
                  exchange.getIn().getHeader(DigitalOceanHeaders.DROPLET_SIZE, String.class));
          LOG.trace("DropletAction Resize [{}] ", action);
          exchange.getMessage().setBody(action);
      }
  
      private void rebuildDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          if (ObjectHelper.isEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.IMAGE_ID))) {
              throw new IllegalArgumentException(DigitalOceanHeaders.IMAGE_ID + " must be specified");
          }
  
          Action action = getEndpoint().getDigitalOceanClient().rebuildDroplet(dropletId,
                  exchange.getIn().getHeader(DigitalOceanHeaders.IMAGE_ID, Integer.class));
          LOG.trace("Rebuild Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void renameDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          if (ObjectHelper.isEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.NAME))) {
              throw new IllegalArgumentException(DigitalOceanHeaders.NAME + " must be specified");
          }
  
          Action action = getEndpoint().getDigitalOceanClient().renameDroplet(dropletId,
                  exchange.getIn().getHeader(DigitalOceanHeaders.NAME, String.class));
          LOG.trace("Rename Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void changeDropletKernel(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          if (ObjectHelper.isEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.KERNEL_ID))) {
              throw new IllegalArgumentException(DigitalOceanHeaders.KERNEL_ID + " must be specified");
          }
  
          Action action = getEndpoint().getDigitalOceanClient().changeDropletKernel(dropletId,
                  exchange.getIn().getHeader(DigitalOceanHeaders.KERNEL_ID, Integer.class));
          LOG.trace("Change Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void resetDropletPassword(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().resetDropletPassword(dropletId);
          LOG.trace("Reset password Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void powerOnDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().powerOnDroplet(dropletId);
          LOG.trace("Power on Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void powerOffDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().powerOffDroplet(dropletId);
          LOG.trace("Power off Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void shutdownDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().shutdownDroplet(dropletId);
          LOG.trace("Shutdown Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void powerCycleDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().powerCycleDroplet(dropletId);
          LOG.trace("Power cycle Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void enableDropletBackups(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().enableDropletBackups(dropletId);
          LOG.trace("Enable backups Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void disableDropletBackups(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().disableDropletBackups(dropletId);
          LOG.trace("Disable backups for Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void enableDropletIpv6(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().enableDropletIpv6(dropletId);
          LOG.trace("Enable IP v6 for Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void enableDropletPrivateNetworking(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().enableDropletPrivateNetworking(dropletId);
          LOG.trace("Enable private networking for Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void rebootDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action = getEndpoint().getDigitalOceanClient().rebootDroplet(dropletId);
          LOG.trace("Reboot Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void takeDropletSnapshot(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          Action action;
  
          if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.NAME))) {
              action = getEndpoint().getDigitalOceanClient().takeDropletSnapshot(dropletId,
                      exchange.getIn().getHeader(DigitalOceanHeaders.NAME, String.class));
          } else {
              action = getEndpoint().getDigitalOceanClient().takeDropletSnapshot(dropletId);
          }
  
          LOG.trace("Take Snapshot for Droplet {} : [{}] ", dropletId, action);
          exchange.getMessage().setBody(action);
      }
  
      private void tagDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          if (ObjectHelper.isEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.NAME))) {
              throw new IllegalArgumentException(DigitalOceanHeaders.NAME + " must be specified");
          }
  
          ArrayList<Resource> resources = new ArrayList<>(1);
          resources.add(new Resource(dropletId.toString(), ResourceType.DROPLET));
          Response response = getEndpoint().getDigitalOceanClient().tagResources(dropletId.toString(), resources);
          LOG.trace("Tag Droplet {} : [{}] ", dropletId, response);
          exchange.getMessage().setBody(response);
      }
  
      private void untagDroplet(Exchange exchange) throws RequestUnsuccessfulException, DigitalOceanException {
          if (ObjectHelper.isEmpty(exchange.getIn().getHeader(DigitalOceanHeaders.NAME))) {
              throw new IllegalArgumentException(DigitalOceanHeaders.NAME + " must be specified");
          }
  
          ArrayList<Resource> resources = new ArrayList<>(1);
          resources.add(new Resource(dropletId.toString(), ResourceType.DROPLET));
          Response response = getEndpoint().getDigitalOceanClient().untagResources(dropletId.toString(), resources);
          LOG.trace("Untag Droplet {} : [{}] ", dropletId, response);
          exchange.getMessage().setBody(response);
      }
  
  }
  