/*
 * 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.jclouds.karaf.core;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.RunScriptOnNodesException;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.scriptbuilder.domain.Statement;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;

/**
 * A proxy implementations of the {@link ComputeService} which delegates calls to the underlying impl and notifies
 * {@link NodeListener}s about node creation/destruction events.
 */
public class ComputeServiceEventProxy implements ComputeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ComputeServiceEventProxy.class);

    private BundleContext bundleContext;
    private ComputeService computeService;

    private ServiceTracker listenerTracker;

    /**
     * Constructor
     *
     * @param bundleContext
     * @param computeService
     */
    public ComputeServiceEventProxy(BundleContext bundleContext, ComputeService computeService) {
        this.bundleContext = bundleContext;
        this.computeService = computeService;
        this.listenerTracker = new ServiceTracker(bundleContext, NodeListener.class.getName(), null);
        this.listenerTracker.open();
    }

    private List<? extends NodeListener> getNodeListeners() {
        List<NodeListener> listeners = new LinkedList<NodeListener>();
        try {
            listeners.addAll(Arrays.asList((NodeListener[]) listenerTracker.getServices()));
        } catch (Exception ex) {
            LOGGER.warn("Could not lookup node listeners. Listeners will not receive the last event.");
        }
        return listeners;
    }

    /**
     * @return a reference to the context that created this ComputeService.
     */
    @Override
    public ComputeServiceContext getContext() {
        return computeService.getContext();
    }

    /**
     * Makes a new template builder for this service
     */
    @Override
    public TemplateBuilder templateBuilder() {
        return computeService.templateBuilder();
    }

    /**
     * Makes a new set of options for running nodes
     */
    @Override
    public TemplateOptions templateOptions() {
        return computeService.templateOptions();
    }

    /**
     * The list hardware profiles command shows you the options including virtual cpu count, memory,
     * and disks. cpu count is not a portable quantity across clouds, as they are measured
     * differently. However, it is a good indicator of relative speed within a cloud. memory is
     * measured in megabytes and disks in gigabytes.
     *
     * @return a map of hardware profiles by ID, conceding that in some clouds the "id" is not used.
     */
    @Override
    public Set<? extends Hardware> listHardwareProfiles() {
        return computeService.listHardwareProfiles();
    }

    /**
     * Images define the operating system and metadata related to a node. In some clouds, Images are
     * bound to a specific region, and their identifiers are different across these regions. For this
     * reason, you should consider matching image requirements like operating system family with
     * TemplateBuilder as opposed to choosing an image explicitly. The getImages() command returns a
     * map of images by id.
     */
    @Override
    public Set<? extends Image> listImages() {
        return computeService.listImages();
    }

    /**
     * all nodes available to the current user by id. If possible, the returned set will include
     * {@link org.jclouds.compute.domain.NodeMetadata} objects.
     */
    @Override
    public Set<? extends ComputeMetadata> listNodes() {
        return computeService.listNodes();
    }

    /**
     * all nodes available to the current user that have the given id. If possible, the returned set will include
     * {@link org.jclouds.compute.domain.NodeMetadata} objects.
     */
    @Override
    public Set<? extends ComputeMetadata> listNodesByIds(Iterable<String> ids) {
       return computeService.listNodesByIds(ids);
    }

    /**
     * The list locations command returns all the valid locations for nodes. A location has a scope,
     * which is typically region or zone. A region is a general area, like eu-west, where a zone is
     * similar to a datacenter. If a location has a parent, that implies it is within that location.
     * For example a location can be a rack, whose parent is likely to be a zone.
     */
    @Override
    public Set<? extends Location> listAssignableLocations() {
        return computeService.listAssignableLocations();
    }

    /**
     * The compute api treats nodes as a group based on the name you specify. Using this group, you
     * can choose to operate one or many nodes as a logical unit without regard to the implementation
     * details of the cloud.
     * <p/>
     * <p/>
     * The set that is returned will include credentials you can use to ssh into the nodes. The "key"
     * part of the credentials is either a password or a private key. You have to inspect the value
     * to determine this.
     * <p/>
     * <pre>
     * if (node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----"))
     *    // it is a private key, not a password.
     * </pre>
     * <p/>
     * <p/>
     * Note. if all you want to do is execute a script at bootup, you should consider use of the
     * runscript option.
     * <p/>
     * If resources such as security groups are needed, they will be reused or created for you.
     * Inbound port 22 will always be opened up.
     *
     * @param group    - common identifier to group nodes by, cannot contain hyphens
     * @param count    - how many to fire up.
     * @param template - how to configure the nodes
     * @return all of the nodes the api was able to launch in a running state.
     * @throws org.jclouds.compute.RunNodesException
     *          when there's a problem applying options to nodes. Note that successful and failed
     *          nodes are a part of this exception, so be sure to inspect this carefully.
     */
    @Override
    public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) throws RunNodesException {
        Set<? extends NodeMetadata> metadata = computeService.createNodesInGroup(group, count, template);
        try {
            for (NodeListener listener : getNodeListeners()) {
                for (NodeMetadata node : metadata) {
                    listener.nodeCreated(node);
                }
            }
        } catch (Exception ex) {
            LOGGER.error("Error while notifying node listeners.", ex);
        }
        return metadata;
    }

    /**
     * Like {@link org.jclouds.compute.ComputeService#createNodesInGroup(String, int, org.jclouds.compute.domain.Template)}, except that the template
     * is default, equivalent to {@code templateBuilder().any().options(templateOptions)}.
     */
    @Override
    public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions) throws RunNodesException {
        Set<? extends NodeMetadata> metadata = computeService.createNodesInGroup(group, count, templateOptions);
        try {
            for (NodeListener listener : getNodeListeners()) {
                for (NodeMetadata node : metadata) {
                    listener.nodeCreated(node);
                }
            }
        } catch (Exception ex) {
            LOGGER.error("Error while notifying node listeners.", ex);
        }
        return metadata;
    }

    /**
     * Like {@link org.jclouds.compute.ComputeService#createNodesInGroup(String, int, org.jclouds.compute.options.TemplateOptions)}, except that the
     * options are default, as specified in {@link org.jclouds.compute.ComputeService#templateOptions}.
     */
    @Override
    public Set<? extends NodeMetadata> createNodesInGroup(String group, int count) throws RunNodesException {
        Set<? extends NodeMetadata> metadata = computeService.createNodesInGroup(group, count);
        try {
            for (NodeListener listener : getNodeListeners()) {
                for (NodeMetadata node : metadata) {
                    listener.nodeCreated(node);
                }
            }
        } catch (Exception ex) {
            LOGGER.error("Error while notifying node listeners.", ex);
        }
        return metadata;
    }

    /**
     * resume the node from {@link org.jclouds.compute.domain.NodeState#SUSPENDED suspended} state,
     * given its id.
     * <p/>
     * <h4>note</h4>
     * <p/>
     * affected nodes may not resume with the same IP address(es)
     */
    @Override
    public void resumeNode(String id) {
        computeService.resumeNode(id);
    }

    /**
     * nodes matching the filter are treated as a logical set. Using the resume command, you can save
     * time by resuming the nodes in parallel.
     * <p/>
     * <h4>note</h4>
     * <p/>
     * affected nodes may not resume with the same IP address(es)
     *
     * @return list of nodes resumed
     *
     * @throws UnsupportedOperationException if the underlying provider doesn't support suspend/resume
     * @throws java.util.NoSuchElementException
     *                                       if no nodes matched the predicate specified
     */
    @Override
    public Set<? extends NodeMetadata> resumeNodesMatching(Predicate<? super NodeMetadata> filter) {
        return computeService.resumeNodesMatching(filter);
    }

    /**
     * suspend the node, given its id. This will result in
     * {@link org.jclouds.compute.domain.NodeState#SUSPENDED suspended} state.
     * <p/>
     * <h4>note</h4>
     * <p/>
     * affected nodes may not resume with the same IP address(es)
     *
     * @throws UnsupportedOperationException if the underlying provider doesn't support suspend/resume
     */
    @Override
    public void suspendNode(String id) {
        computeService.suspendNode(id);
    }

    /**
     * nodes matching the filter are treated as a logical set. Using the suspend command, you can
     * save time by suspending the nodes in parallel.
     * <p/>
     * <h4>note</h4>
     * <p/>
     * affected nodes may not resume with the same IP address(es)
     *
     * @return list of nodes suspended
     *
     * @throws UnsupportedOperationException if the underlying provider doesn't support suspend/resume
     * @throws java.util.NoSuchElementException
     *                                       if no nodes matched the predicate specified
     */
    @Override
    public Set<? extends NodeMetadata> suspendNodesMatching(Predicate<? super NodeMetadata> filter) {
        return computeService.suspendNodesMatching(filter);
    }

    /**
     * destroy the node, given its id. If it is the only node in a tag set, the dependent resources
     * will also be destroyed.
     */
    @Override
    public void destroyNode(String id) {
        NodeMetadata node = null;
        try {
            node = computeService.getNodeMetadata(id);
        } catch (Exception ex) {
            LOGGER.error("Error while retrieving node metadata.", ex);
        }
        computeService.destroyNode(id);
        try {
            for (NodeListener listener : getNodeListeners()) {
                listener.nodeDestroyed(node);
            }
        } catch (Exception ex) {
            LOGGER.error("Error while notifying node listeners.", ex);
        }

    }

    /**
     * nodes matching the filter are treated as a logical set. Using the delete command, you can save
     * time by removing the nodes in parallel. When the last node in a set is destroyed, any indirect
     * resources it uses, such as keypairs, are also destroyed.
     *
     * @return list of nodes destroyed
     */
    @Override
    public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<? super NodeMetadata> filter) {
        Set<? extends NodeMetadata> metadata = computeService.destroyNodesMatching(filter);
        try {
            for (NodeListener listener : getNodeListeners()) {
                for (NodeMetadata node : metadata) {
                    listener.nodeCreated(node);
                }
            }
        } catch (Exception ex) {
            LOGGER.error("Error while notifying node listeners.", ex);
        }
        return metadata;
    }

    /**
     * reboot the node, given its id.
     */
    @Override
    public void rebootNode(String id) {
        computeService.rebootNode(id);
    }

    /**
     * nodes matching the filter are treated as a logical set. Using this command, you can save time
     * by rebooting the nodes in parallel.
     *
     * @return list of nodes rebooted
     *
     * @throws java.util.NoSuchElementException
     *          if no nodes matched the predicate specified
     */
    @Override
    public Set<? extends NodeMetadata> rebootNodesMatching(Predicate<? super NodeMetadata> filter) {
        return computeService.rebootNodesMatching(filter);
    }

    /**
     * Find a node by its id.
     */
    @Override
    public NodeMetadata getNodeMetadata(String id) {
        return computeService.getNodeMetadata(id);
    }

    /**
     * get all nodes including details such as image and ip addresses even if it incurs extra
     * requests to the service.
     *
     * @param filter how to select the nodes you are interested in details on.
     */
    @Override
    public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<? super NodeMetadata> filter) {
        return computeService.listNodesDetailsMatching(filter);
    }

    /**
     * @see org.jclouds.compute.ComputeService#runScriptOnNodesMatching(com.google.common.base.Predicate, org.jclouds.scriptbuilder.domain.Statement, org.jclouds.compute.options.RunScriptOptions)
     */
    @Override
    public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<? super NodeMetadata> filter, String runScript) throws RunScriptOnNodesException {
        return computeService.runScriptOnNodesMatching(filter, runScript);
    }

    /**
     * @see org.jclouds.compute.ComputeService#runScriptOnNodesMatching(com.google.common.base.Predicate, org.jclouds.scriptbuilder.domain.Statement, org.jclouds.compute.options.RunScriptOptions)
     */
    @Override
    public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<? super NodeMetadata> filter, Statement runScript) throws RunScriptOnNodesException {
        return computeService.runScriptOnNodesMatching(filter, runScript);
    }

    /**
     * @see org.jclouds.compute.ComputeService#runScriptOnNodesMatching(com.google.common.base.Predicate, org.jclouds.scriptbuilder.domain.Statement, org.jclouds.compute.options.RunScriptOptions)
     */
    @Override
    public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<? super NodeMetadata> filter, String runScript, RunScriptOptions options) throws RunScriptOnNodesException {
        return computeService.runScriptOnNodesMatching(filter, runScript, options);
    }

    /**
     * Run the script on all nodes with the specific predicate.
     *
     * @param filter    Predicate-based filter to define on which nodes the script is to be executed
     * @param runScript statement containing the script to run
     * @param options   nullable options to how to run the script, whether to override credentials
     * @return map with node identifiers and corresponding responses
     * @throws java.util.NoSuchElementException
     *          if no nodes matched the predicate specified
     * @throws org.jclouds.compute.RunScriptOnNodesException
     *          if anything goes wrong during script execution
     * @see org.jclouds.compute.predicates.NodePredicates#runningInGroup(String)
     * @see org.jclouds.scriptbuilder.domain.Statements
     */
    @Override
    public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<? super NodeMetadata> filter, Statement runScript, RunScriptOptions options) throws RunScriptOnNodesException {
        return computeService.runScriptOnNodesMatching(filter, runScript, options);
    }

    /**
     * Run the script on a specific node
     *
     * @param id        node the script is to be executed on
     * @param runScript statement containing the script to run
     * @param options   nullable options to how to run the script, whether to override credentials
     * @return map with node identifiers and corresponding responses
     * @throws java.util.NoSuchElementException
     *                               if the node is not found
     * @throws IllegalStateException if the node is not in running state
     * @throws org.jclouds.compute.callables.ScriptStillRunningException
     *                               if the script was still running after {@link org.jclouds.compute.reference.ComputeServiceConstants.Timeouts#scriptComplete}
     * @see org.jclouds.compute.predicates.NodePredicates#runningInGroup(String)
     * @see org.jclouds.scriptbuilder.domain.Statements
     */
    @Override
    public ExecResponse runScriptOnNode(String id, Statement runScript, RunScriptOptions options) {
        return computeService.runScriptOnNode(id, runScript, options);
    }

    @Override
    public ListenableFuture<ExecResponse> submitScriptOnNode(String s, String s2, RunScriptOptions runScriptOptions) {
        return computeService.submitScriptOnNode(s, s2, runScriptOptions);
    }

    /**
     * Run the script on a specific node in the background, typically as {@code nohup}
     *
     * @param id        node the script is to be executed on
     * @param runScript statement containing the script to run
     * @param options   nullable options to how to run the script, whether to override credentials
     * @return map with node identifiers and corresponding responses
     * @throws java.util.NoSuchElementException
     *                               if the node is not found
     * @throws IllegalStateException if the node is not in running state
     * @see org.jclouds.compute.predicates.NodePredicates#runningInGroup(String)
     * @see org.jclouds.scriptbuilder.domain.Statements
     */
    @Override
    @Beta
    public ListenableFuture<ExecResponse> submitScriptOnNode(String id, Statement runScript, RunScriptOptions options) {
        return computeService.submitScriptOnNode(id, runScript, options);
    }

    /**
     * @see #runScriptOnNode(String, org.jclouds.scriptbuilder.domain.Statement, org.jclouds.compute.options.RunScriptOptions)
     */
    @Override
    public ExecResponse runScriptOnNode(String id, Statement runScript) {
        return computeService.runScriptOnNode(id, runScript);
    }

    /**
     * @see #runScriptOnNode(String, org.jclouds.scriptbuilder.domain.Statement, org.jclouds.compute.options.RunScriptOptions)
     * @see org.jclouds.scriptbuilder.domain.Statements#exec
     */
    @Override
    public ExecResponse runScriptOnNode(String id, String runScript, RunScriptOptions options) {
        return computeService.runScriptOnNode(id, runScript, options);
    }

    /**
     * @see #runScriptOnNode(String, String, org.jclouds.compute.options.RunScriptOptions)
     */
    @Override
    public ExecResponse runScriptOnNode(String id, String runScript) {
        return computeService.runScriptOnNode(id, runScript);
    }

    /**
     * Find an image by its id.
     * <p/>
     * <h3>note</h3>
     * <p/>
     * This is an uncached call to the backend service
     */
    @Override
    public Image getImage(String id) {
        return computeService.getImage(id);
    }

    /**
     * Returns the {@link org.jclouds.compute.extensions.ImageExtension} for this provider if it implements it.
     *
     * @return an optional of the {@link org.jclouds.compute.extensions.ImageExtension} or {@link com.google.common.base.Optional#absent()} if not
     *         implemented
     */
    @Override
    public Optional<ImageExtension> getImageExtension() {
        return computeService.getImageExtension();
    }

    /**
     * Returns the {@link org.jclouds.compute.extensions.SecurityGroupExtension} for this provider if it implements it.
     *
     * @return an optional of the {@link org.jclouds.compute.extensions.SecurityGroupExtension} or {@link com.google.common.base.Optional#absent()} if not
     *         implemented
     */
    @Override
    public Optional<SecurityGroupExtension> getSecurityGroupExtension() {
        return computeService.getSecurityGroupExtension();
    }
}
