/* (non-Javadoc)
   * @see org.opennms.features.pluginmgr.PluginManager#getAvailablePlugins()
   */
  @Override
  public synchronized ProductSpecList getAvailablePlugins() {

    if (pluginModelJaxb.getAvailablePlugins() == null
        || pluginModelJaxb.getAvailablePlugins().getProductSpecList() == null
        || pluginModelJaxb.getAvailablePlugins().getProductSpecList().size() == 0)
      refreshAvailablePlugins();

    return pluginModelJaxb.getAvailablePlugins();
  }
  /* (non-Javadoc)
   * @see org.opennms.features.pluginmgr.PluginManager#addPluginToManifest(java.lang.String, java.lang.String)
   */
  @Override
  public synchronized void addPluginToManifest(String selectedProductId, String karafInstance) {
    if (karafInstance == null) throw new RuntimeException("karafInstance cannot be null");
    if (selectedProductId == null) throw new RuntimeException("selectedProductId cannot be null");

    SortedMap<String, KarafManifestEntryJaxb> karafInstances = getKarafInstances();
    if (!karafInstances.containsKey(karafInstance))
      throw new RuntimeException("system does not know karafInstance=" + karafInstance);

    ProductMetadata productMetadata = null;
    for (ProductMetadata pMetadata : pluginModelJaxb.getAvailablePlugins().getProductSpecList()) {
      if (selectedProductId.equals(pMetadata.getProductId())) {
        productMetadata = pMetadata;
        break;
      }
    }
    if (productMetadata == null)
      throw new RuntimeException("cannot install unknown available productId=" + selectedProductId);
    if (productMetadata.getFeatureRepository() == null)
      throw new RuntimeException(
          "feature repository cannot be null for productId=" + selectedProductId);

    if (!pluginModelJaxb.getKarafManifestEntryMap().containsKey(karafInstance)) {
      pluginModelJaxb.getKarafManifestEntryMap().put(karafInstance, new KarafManifestEntryJaxb());
    }

    ProductSpecList karafInstancePluginManifest =
        pluginModelJaxb.getKarafManifestEntryMap().get(karafInstance).getPluginManifest();

    // remove any product metadata with duplicate productId's from the list
    String productMetadataId = productMetadata.getProductId();
    ArrayList<ProductMetadata> searchlist =
        new ArrayList<ProductMetadata>(karafInstancePluginManifest.getProductSpecList());
    for (ProductMetadata searchProductMetadata : searchlist) {
      if (productMetadataId.equals(searchProductMetadata.getProductId())) {
        karafInstancePluginManifest.getProductSpecList().remove(searchProductMetadata);
      }
    }

    karafInstancePluginManifest.getProductSpecList().add(productMetadata);

    persist();
  }
  /* (non-Javadoc)
   * @see org.opennms.features.pluginmgr.PluginManager#installPlugin(java.lang.String, java.lang.String)
   */
  @Override
  public synchronized void installPlugin(String selectedProductId, String karafInstance) {
    if (karafInstance == null) throw new RuntimeException("karafInstance cannot be null");
    if (selectedProductId == null) throw new RuntimeException("selectedProductId cannot be null");

    SortedMap<String, KarafManifestEntryJaxb> karafInstances = getKarafInstances();
    if (!karafInstances.containsKey(karafInstance))
      throw new RuntimeException("system does not know karafInstance=" + karafInstance);
    KarafManifestEntryJaxb karafManifest = karafInstances.get(karafInstance);
    String karafInstanceUrl = karafManifest.getKarafInstanceUrl();

    // only update remote if accessible
    if (karafManifest.getRemoteIsAccessible() == null || !karafManifest.getRemoteIsAccessible()) {
      throw new RuntimeException("karafInstance=" + karafInstance + " is not accessable remotely");
    }

    ProductMetadata productMetadata = null;

    // try manifest plugins list first
    if (pluginModelJaxb.getKarafManifestEntryMap().get(karafInstance) != null) {
      ProductSpecList karafInstancePluginManifest =
          pluginModelJaxb.getKarafManifestEntryMap().get(karafInstance).getPluginManifest();
      if (karafInstancePluginManifest != null) {
        for (ProductMetadata pMetadata : karafInstancePluginManifest.getProductSpecList()) {
          if (selectedProductId.equals(pMetadata.getProductId())) {
            productMetadata = pMetadata;
            break;
          }
        }
      }
    }

    // then try available plugins
    if (productMetadata == null) {
      for (ProductMetadata pMetadata : pluginModelJaxb.getAvailablePlugins().getProductSpecList()) {
        if (selectedProductId.equals(pMetadata.getProductId())) {
          productMetadata = pMetadata;
          break;
        }
      }
    }

    if (productMetadata == null)
      throw new RuntimeException("cannot install unknown available productId=" + selectedProductId);
    if (productMetadata.getFeatureRepository() == null)
      throw new RuntimeException(
          "feature repository cannot be null for productId=" + selectedProductId);

    FeaturesServiceClientRestJerseyImpl featuresServiceClient =
        new FeaturesServiceClientRestJerseyImpl();
    featuresServiceClient.setBaseUrl(karafInstanceUrl);
    featuresServiceClient.setUserName(karafManifest.getKarafInstanceUserName());
    featuresServiceClient.setPassword(karafManifest.getKarafInstancePassword());
    featuresServiceClient.setBasePath(FEATURE_MGR_BASE_PATH);

    try {
      // add feature repository
      featuresServiceClient.featuresAddRepository(productMetadata.getFeatureRepository());
      // a feature id looks like name/version.
      String version = null;
      String name = null;
      if (selectedProductId.contains("/")) {
        int i = selectedProductId.indexOf('/');
        version = selectedProductId.substring(i + 1);
        name = selectedProductId.substring(0, selectedProductId.indexOf('/'));
      }
      // add feature
      featuresServiceClient.featuresInstall(name, version);
      refreshKarafEntry(karafInstance);
    } catch (Exception e) {
      throw new RuntimeException(
          "problem installing product "
              + selectedProductId
              + " for Karaf Instance="
              + karafInstance
              + " karafInstanceUrl="
              + karafInstanceUrl
              + ": ",
          e);
    }
  }