/*
 * 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.brooklyn.feed.jmx;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;

import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.feed.AbstractFeed;
import org.apache.brooklyn.core.feed.AttributePollHandler;
import org.apache.brooklyn.core.feed.DelegatingPollHandler;
import org.apache.brooklyn.core.feed.PollHandler;
import org.apache.brooklyn.core.feed.Poller;
import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.reflect.TypeToken;


/**
 * Provides a feed of attribute values, by polling or subscribing over jmx.
 * 
 * Example usage (e.g. in an entity that extends {@link SoftwareProcessImpl}):
 * <pre>
 * {@code
 * private JmxFeed feed;
 * 
 * //@Override
 * protected void connectSensors() {
 *   super.connectSensors();
 *   
 *   feed = JmxFeed.builder()
 *       .entity(this)
 *       .period(500, TimeUnit.MILLISECONDS)
 *       .pollAttribute(new JmxAttributePollConfig<Integer>(ERROR_COUNT)
 *           .objectName(requestProcessorMbeanName)
 *           .attributeName("errorCount"))
 *       .pollAttribute(new JmxAttributePollConfig<Boolean>(SERVICE_UP)
 *           .objectName(serverMbeanName)
 *           .attributeName("Started")
 *           .onError(Functions.constant(false)))
 *       .build();
 * }
 * 
 * {@literal @}Override
 * protected void disconnectSensors() {
 *   super.disconnectSensors();
 *   if (feed != null) feed.stop();
 * }
 * }
 * </pre>
 * 
 * @author aled
 */
public class JmxFeed extends AbstractFeed {

    public static final Logger log = LoggerFactory.getLogger(JmxFeed.class);

    public static final long JMX_CONNECTION_TIMEOUT_MS = 120*1000;

    public static final ConfigKey<JmxHelper> HELPER = ConfigKeys.newConfigKey(JmxHelper.class, "helper");
    public static final ConfigKey<Boolean> OWN_HELPER = ConfigKeys.newBooleanConfigKey("ownHelper");
    public static final ConfigKey<String> JMX_URI = ConfigKeys.newStringConfigKey("jmxUri");
    public static final ConfigKey<Long> JMX_CONNECTION_TIMEOUT = ConfigKeys.newLongConfigKey("jmxConnectionTimeout");
    
    @SuppressWarnings("serial")
    public static final ConfigKey<SetMultimap<String, JmxAttributePollConfig<?>>> ATTRIBUTE_POLLS = ConfigKeys.newConfigKey(
            new TypeToken<SetMultimap<String, JmxAttributePollConfig<?>>>() {},
            "attributePolls");

    @SuppressWarnings("serial")
    public static final ConfigKey<SetMultimap<List<?>, JmxOperationPollConfig<?>>> OPERATION_POLLS = ConfigKeys.newConfigKey(
            new TypeToken<SetMultimap<List<?>, JmxOperationPollConfig<?>>>() {},
            "operationPolls");

    @SuppressWarnings("serial")
    public static final ConfigKey<SetMultimap<NotificationFilter, JmxNotificationSubscriptionConfig<?>>> NOTIFICATION_SUBSCRIPTIONS = ConfigKeys.newConfigKey(
            new TypeToken<SetMultimap<NotificationFilter, JmxNotificationSubscriptionConfig<?>>>() {},
            "notificationPolls");

    public static Builder builder() {
        return new Builder();
    }
    
    public static class Builder {
        private EntityLocal entity;
        private JmxHelper helper;
        private long jmxConnectionTimeout = JMX_CONNECTION_TIMEOUT_MS;
        private long period = 500;
        private TimeUnit periodUnits = TimeUnit.MILLISECONDS;
        private List<JmxAttributePollConfig<?>> attributePolls = Lists.newArrayList();
        private List<JmxOperationPollConfig<?>> operationPolls = Lists.newArrayList();
        private List<JmxNotificationSubscriptionConfig<?>> notificationSubscriptions = Lists.newArrayList();
        private String uniqueTag;
        private volatile boolean built;
        
        public Builder entity(EntityLocal val) {
            this.entity = val;
            return this;
        }
        public Builder helper(JmxHelper val) {
            this.helper = val;
            return this;
        }
        public Builder period(Duration duration) {
            return period(duration.toMilliseconds(), TimeUnit.MILLISECONDS);
        }
        public Builder period(long millis) {
            return period(millis, TimeUnit.MILLISECONDS);
        }
        public Builder period(long val, TimeUnit units) {
            this.period = val;
            this.periodUnits = units;
            return this;
        }
        public Builder pollAttribute(JmxAttributePollConfig<?> config) {
            attributePolls.add(config);
            return this;
        }
        public Builder pollOperation(JmxOperationPollConfig<?> config) {
            operationPolls.add(config);
            return this;
        }
        public Builder subscribeToNotification(JmxNotificationSubscriptionConfig<?> config) {
            notificationSubscriptions.add(config);
            return this;
        }
        public Builder uniqueTag(String uniqueTag) {
            this.uniqueTag = uniqueTag;
            return this;
        }
        public JmxFeed build() {
            built = true;
            JmxFeed result = new JmxFeed(this);
            result.setEntity(checkNotNull(entity, "entity"));
            result.start();
            return result;
        }
        @Override
        protected void finalize() {
            if (!built) log.warn("JmxFeed.Builder created, but build() never called");
        }
    }

    private final SetMultimap<ObjectName, NotificationListener> notificationListeners = HashMultimap.create();

    /**
     * For rebind; do not call directly; use builder
     */
    public JmxFeed() {
    }

    protected JmxFeed(Builder builder) {
        super();
        if (builder.helper != null) {
            JmxHelper helper = builder.helper;
            setConfig(HELPER, helper);
            setConfig(OWN_HELPER, false);
            setConfig(JMX_URI, helper.getUrl());
        }
        setConfig(JMX_CONNECTION_TIMEOUT, builder.jmxConnectionTimeout);
        
        SetMultimap<String, JmxAttributePollConfig<?>> attributePolls = HashMultimap.<String,JmxAttributePollConfig<?>>create();
        for (JmxAttributePollConfig<?> config : builder.attributePolls) {
            if (!config.isEnabled()) continue;
            @SuppressWarnings({ "rawtypes", "unchecked" })
            JmxAttributePollConfig<?> configCopy = new JmxAttributePollConfig(config);
            if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);
            attributePolls.put(configCopy.getObjectName().getCanonicalName() + configCopy.getAttributeName(), configCopy);
        }
        setConfig(ATTRIBUTE_POLLS, attributePolls);
        
        SetMultimap<List<?>, JmxOperationPollConfig<?>> operationPolls = HashMultimap.<List<?>,JmxOperationPollConfig<?>>create();
        for (JmxOperationPollConfig<?> config : builder.operationPolls) {
            if (!config.isEnabled()) continue;
            @SuppressWarnings({ "rawtypes", "unchecked" })
            JmxOperationPollConfig<?> configCopy = new JmxOperationPollConfig(config);
            if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);
            operationPolls.put(configCopy.buildOperationIdentity(), configCopy);
        }
        setConfig(OPERATION_POLLS, operationPolls);
        
        SetMultimap<NotificationFilter, JmxNotificationSubscriptionConfig<?>> notificationSubscriptions = HashMultimap.create();
        for (JmxNotificationSubscriptionConfig<?> config : builder.notificationSubscriptions) {
            if (!config.isEnabled()) continue;
            notificationSubscriptions.put(config.getNotificationFilter(), config);
        }
        setConfig(NOTIFICATION_SUBSCRIPTIONS, notificationSubscriptions);
        initUniqueTag(builder.uniqueTag, attributePolls, operationPolls, notificationSubscriptions);
    }

    @Override
    public void setEntity(EntityLocal entity) {
        if (getConfig(HELPER) == null) {
            JmxHelper helper = new JmxHelper(entity);
            setConfig(HELPER, helper);
            setConfig(OWN_HELPER, true);
            setConfig(JMX_URI, helper.getUrl());
        }
        super.setEntity(entity);
    }
    
    public String getJmxUri() {
        return getConfig(JMX_URI);
    }
    
    protected JmxHelper getHelper() {
        return getConfig(HELPER);
    }
    
    @SuppressWarnings("unchecked")
    protected Poller<Object> getPoller() {
        return (Poller<Object>) super.getPoller();
    }
    
    @Override
    protected boolean isConnected() {
        return super.isConnected() && getHelper().isConnected();
    }
    
    @Override
    protected void preStart() {
        /*
         * All actions on the JmxHelper are done async (through the poller's threading) so we don't 
         * block on start/rebind if the entity is unreachable 
         * (without this we get a 120s pause in JmxHelper.connect restarting)
         */
        final SetMultimap<NotificationFilter, JmxNotificationSubscriptionConfig<?>> notificationSubscriptions = getConfig(NOTIFICATION_SUBSCRIPTIONS);
        final SetMultimap<List<?>, JmxOperationPollConfig<?>> operationPolls = getConfig(OPERATION_POLLS);
        final SetMultimap<String, JmxAttributePollConfig<?>> attributePolls = getConfig(ATTRIBUTE_POLLS);
        
        getPoller().submit(new Callable<Void>() {
               public Void call() {
                   getHelper().connect(getConfig(JMX_CONNECTION_TIMEOUT));
                   return null;
               }
               @Override public String toString() { return "Connect JMX "+getHelper().getUrl(); }
           });
        
        for (final NotificationFilter filter : notificationSubscriptions.keySet()) {
            getPoller().submit(new Callable<Void>() {
                public Void call() {
                    // TODO Could config.getObjectName have wildcards? Is this code safe?
                    Set<JmxNotificationSubscriptionConfig<?>> configs = notificationSubscriptions.get(filter);
                    NotificationListener listener = registerNotificationListener(configs);
                    ObjectName objectName = Iterables.get(configs, 0).getObjectName();
                    notificationListeners.put(objectName, listener);
                    return null;
                }
                @Override public String toString() { return "Register JMX notifications: "+notificationSubscriptions.get(filter); }
            });
        }
        
        // Setup polling of sensors
        for (final String jmxAttributeName : attributePolls.keys()) {
            registerAttributePoller(attributePolls.get(jmxAttributeName));
        }
        
        // Setup polling of operations
        for (final List<?> operationIdentifier : operationPolls.keys()) {
            registerOperationPoller(operationPolls.get(operationIdentifier));
        }
    }
    
    @Override
    protected void preStop() {
        super.preStop();

        for (Map.Entry<ObjectName, NotificationListener> entry : notificationListeners.entries()) {
            unregisterNotificationListener(entry.getKey(), entry.getValue());
        }
        notificationListeners.clear();
    }
    
    @Override
    protected void postStop() {
        super.postStop();
        JmxHelper helper = getHelper();
        Boolean ownHelper = getConfig(OWN_HELPER);
        if (helper != null && ownHelper) helper.terminate();
    }
    
    /**
     * Registers to poll a jmx-operation for an ObjectName, where all the given configs are for the same ObjectName + operation + parameters.
     */
    private void registerOperationPoller(Set<JmxOperationPollConfig<?>> configs) {
        Set<AttributePollHandler<? super Object>> handlers = Sets.newLinkedHashSet();
        long minPeriod = Integer.MAX_VALUE;
        
        final ObjectName objectName = Iterables.get(configs, 0).getObjectName();
        final String operationName = Iterables.get(configs, 0).getOperationName();
        final List<String> signature = Iterables.get(configs, 0).getSignature();
        final List<?> params = Iterables.get(configs, 0).getParams();
        
        for (JmxOperationPollConfig<?> config : configs) {
            handlers.add(new AttributePollHandler<Object>(config, getEntity(), this));
            if (config.getPeriod() > 0) minPeriod = Math.min(minPeriod, config.getPeriod());
        }
        
        getPoller().scheduleAtFixedRate(
                new Callable<Object>() {
                    public Object call() throws Exception {
                        if (log.isDebugEnabled()) log.debug("jmx operation polling for {} sensors at {} -> {}", new Object[] {getEntity(), getJmxUri(), operationName});
                        if (signature.size() == params.size()) {
                            return getHelper().operation(objectName, operationName, signature, params);
                        } else {
                            return getHelper().operation(objectName, operationName, params.toArray());
                        }
                    }
                }, 
                new DelegatingPollHandler<Object>(handlers), minPeriod);
    }

    /**
     * Registers to poll a jmx-attribute for an ObjectName, where all the given configs are for that same ObjectName + attribute.
     */
    private void registerAttributePoller(Set<JmxAttributePollConfig<?>> configs) {
        Set<AttributePollHandler<? super Object>> handlers = Sets.newLinkedHashSet();
        long minPeriod = Integer.MAX_VALUE;
        
        final ObjectName objectName = Iterables.get(configs, 0).getObjectName();
        final String jmxAttributeName = Iterables.get(configs, 0).getAttributeName();
        
        for (JmxAttributePollConfig<?> config : configs) {
            handlers.add(new AttributePollHandler<Object>(config, getEntity(), this));
            if (config.getPeriod() > 0) minPeriod = Math.min(minPeriod, config.getPeriod());
        }
        
        // TODO Not good calling this holding the synchronization lock
        getPoller().scheduleAtFixedRate(
                new Callable<Object>() {
                    public Object call() throws Exception {
                        if (log.isTraceEnabled()) log.trace("jmx attribute polling for {} sensors at {} -> {}", new Object[] {getEntity(), getJmxUri(), jmxAttributeName});
                        return getHelper().getAttribute(objectName, jmxAttributeName);
                    }
                }, 
                new DelegatingPollHandler<Object>(handlers), minPeriod);
    }

    /**
     * Registers to subscribe to notifications for an ObjectName, where all the given configs are for that same ObjectName + filter.
     */
    private NotificationListener registerNotificationListener(Set<JmxNotificationSubscriptionConfig<?>> configs) {
        final List<AttributePollHandler<? super javax.management.Notification>> handlers = Lists.newArrayList();

        final ObjectName objectName = Iterables.get(configs, 0).getObjectName();
        final NotificationFilter filter = Iterables.get(configs, 0).getNotificationFilter();

        for (final JmxNotificationSubscriptionConfig<?> config : configs) {
            AttributePollHandler<javax.management.Notification> handler = new AttributePollHandler<javax.management.Notification>(config, getEntity(), this) {
                @Override protected Object transformValueOnSuccess(javax.management.Notification val) {
                    if (config.getOnNotification() != null) {
                        return config.getOnNotification().apply(val);
                    } else {
                        Object result = super.transformValueOnSuccess(val);
                        if (result instanceof javax.management.Notification)
                            return ((javax.management.Notification)result).getUserData();
                        return result;
                    }
                }
            };
            handlers.add(handler);
        }
        final PollHandler<javax.management.Notification> compoundHandler = new DelegatingPollHandler<javax.management.Notification>(handlers);
        
        NotificationListener listener = new NotificationListener() {
            @Override public void handleNotification(Notification notification, Object handback) {
                compoundHandler.onSuccess(notification);
            }
        };
        getHelper().addNotificationListener(objectName, listener, filter);
        
        return listener;
    }
    
    private void unregisterNotificationListener(ObjectName objectName, NotificationListener listener) {
        try {
            getHelper().removeNotificationListener(objectName, listener);
        } catch (RuntimeException e) {
            log.warn("Failed to unregister listener: "+objectName+", "+listener+"; continuing...", e);
        }
    }
    
    @Override
    public String toString() {
        return "JmxFeed["+(getManagementContext()!=null&&getManagementContext().isRunning()?getJmxUri():"mgmt-not-running")+"]";
    }
}
