/*
 * 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 SF 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.felix.hc.core.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ReflectionException;
import org.apache.felix.hc.api.HealthCheck;
import org.apache.felix.hc.api.Result;
import org.apache.felix.hc.api.Result.Status;
import org.apache.felix.hc.core.impl.util.AdhocStatusHealthCheck;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Allows to dynamically add a health check that returns WARN or CRITICAL for certain tags for testing purposes or go-live sequences. Uses an MBean to
 * add/remove the DynamicTestingHealthCheck dynamically. */
@Component
public class JmxAdjustableStatusHealthCheck {
    private static final Logger LOG = LoggerFactory.getLogger(JmxAdjustableStatusHealthCheck.class);

    public static final String OBJECT_NAME = "org.apache.felix.healthcheck:type=AdjustableStatusHealthCheck";

    private BundleContext bundleContext;

    private ServiceRegistration mbeanRegistration = null;
    private ServiceRegistration healthCheckRegistration = null;

    @Activate
    protected final void activate(final ComponentContext context) {
        this.bundleContext = context.getBundleContext();
        registerMbean();
    }

    @Deactivate
    protected final void deactivate(final ComponentContext context) {
        unregisterMbean();
        unregisterDynamicHealthCheck();
    }

    private void registerMbean() {
        final Dictionary<String, String> mbeanProps = new Hashtable<String, String>();
        mbeanProps.put("jmx.objectname", OBJECT_NAME);
        AdjustableHealthCheckStatusMBean adjustableHealthCheckStatusMBean = new AdjustableHealthCheckStatusMBean();
        this.mbeanRegistration = bundleContext.registerService(DynamicMBean.class.getName(), adjustableHealthCheckStatusMBean, mbeanProps);
        LOG.debug("Registered mbean {} as {}", adjustableHealthCheckStatusMBean, OBJECT_NAME);
    }

    private void unregisterMbean() {
        if (this.mbeanRegistration != null) {
            this.mbeanRegistration.unregister();
            this.mbeanRegistration = null;
            LOG.debug("Unregistered mbean AdjustableHealthCheckStatusMBean");
        }
    }

    /* synchronized as potentially multiple users can run JMX operations */
    private synchronized void registerDynamicHealthCheck(Result.Status status, String[] tags) {
        unregisterDynamicHealthCheck();
        HealthCheck healthCheck = new AdhocStatusHealthCheck(status, "Set dynamically via JMX bean " + JmxAdjustableStatusHealthCheck.OBJECT_NAME);
        Dictionary<String, Object> props = new Hashtable<String, Object>();
        props.put(HealthCheck.NAME, "JMX Adhoc Result");
        props.put(HealthCheck.TAGS, tags);

        healthCheckRegistration = bundleContext.registerService(HealthCheck.class.getName(), healthCheck, props);
    }

    /* synchronized as potentially multiple users can run JMX operations */
    private synchronized void unregisterDynamicHealthCheck() {
        if (this.healthCheckRegistration != null) {
            this.healthCheckRegistration.unregister();
            this.healthCheckRegistration = null;
            LOG.debug("Unregistered DynamicTestingHealthCheck");
        }
    }

    private class AdjustableHealthCheckStatusMBean implements DynamicMBean {

        private static final String OP_RESET = "reset";
        private static final String OP_ADD_WARN_RESULT_FOR_TAGS = "addWarnResultForTags";
        private static final String OP_ADD_TEMPORARILY_UNAVAILABLE_RESULT_FOR_TAGS = "addTemporarilyUnavailableResultForTags";
        private static final String OP_ADD_CRITICAL_RESULT_FOR_TAGS = "addCriticalResultForTags";

        private static final String ATT_TAGS = "tags";
        private static final String ATT_STATUS = "status";

        private static final String STATUS_INACTIVE = "INACTIVE";

        /** The mbean info. */
        private final MBeanInfo mbeanInfo;

        private List<String> tags = new ArrayList<String>();
        private String status = STATUS_INACTIVE;

        public AdjustableHealthCheckStatusMBean() {
            this.mbeanInfo = this.createMBeanInfo();
        }

        @Override
        public Object getAttribute(final String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {

            if (ATT_TAGS.equals(attribute)) {
                return String.join(",", tags);
            } else if (ATT_STATUS.equals(attribute)) {
                return status.toString();
            } else {
                throw new AttributeNotFoundException("Attribute " + attribute + " not found.");
            }
        }

        @Override
        public AttributeList getAttributes(final String[] attributes) {
            final AttributeList result = new AttributeList();
            for (String att : attributes) {
                try {
                    result.add(new Attribute(att, getAttribute(att)));
                } catch (Exception e) {
                    throw new IllegalArgumentException(e.getMessage(), e);
                }
            }
            return result;
        }

        private MBeanInfo createMBeanInfo() {
            final List<MBeanAttributeInfo> attrs = new ArrayList<MBeanAttributeInfo>();

            attrs.add(new MBeanAttributeInfo(ATT_TAGS, String.class.getName(), "Tags", true, false, false));
            attrs.add(new MBeanAttributeInfo(ATT_STATUS, String.class.getName(), "Status", true, false, false));

            MBeanParameterInfo[] params = new MBeanParameterInfo[] {
                    new MBeanParameterInfo(ATT_TAGS, "java.lang.String", "Comma separated list of tags") };

            final List<MBeanOperationInfo> ops = new ArrayList<MBeanOperationInfo>();
            ops.add(new MBeanOperationInfo(OP_RESET, "Resets this testing mechanism and removes the failing HC",
                    new MBeanParameterInfo[0], "java.lang.String", MBeanOperationInfo.ACTION));
            ops.add(new MBeanOperationInfo(OP_ADD_TEMPORARILY_UNAVAILABLE_RESULT_FOR_TAGS, "Adds a TEMPORARILY_UNAVAILABLE result for the given tags",
                    params, "java.lang.String", MBeanOperationInfo.ACTION));
            ops.add(new MBeanOperationInfo(OP_ADD_CRITICAL_RESULT_FOR_TAGS, "Adds a CRITICAL result for the given tags",
                    params, "java.lang.String", MBeanOperationInfo.ACTION));
            ops.add(new MBeanOperationInfo(OP_ADD_WARN_RESULT_FOR_TAGS, "Adds a WARN result for the given tags",
                    params, "java.lang.String", MBeanOperationInfo.ACTION));

            return new MBeanInfo(this.getClass().getName(),
                    "Adjustable Health Check", attrs.toArray(new MBeanAttributeInfo[attrs.size()]), null,
                    ops.toArray(new MBeanOperationInfo[ops.size()]), null);
        }

        @Override
        public MBeanInfo getMBeanInfo() {
            return this.mbeanInfo;
        }

        @Override
        public Object invoke(final String actionName, final Object[] params, final String[] signature)
                throws MBeanException, ReflectionException {
            
            Status newStatus = null;
            
            tags = params.length > 0 ? Arrays.asList(params[0].toString().split("[,; ]+")) : Arrays.asList("");
            
            if (OP_RESET.equals(actionName)) {
                unregisterDynamicHealthCheck();
                LOG.info("JMX-adjustable Health Check was reset");
                status = STATUS_INACTIVE;
                return "Reset successful";
            } else if (OP_ADD_TEMPORARILY_UNAVAILABLE_RESULT_FOR_TAGS.equals(actionName)) {
                newStatus =  Result.Status.TEMPORARILY_UNAVAILABLE;
            } else if (OP_ADD_CRITICAL_RESULT_FOR_TAGS.equals(actionName)) {
                newStatus =  Result.Status.CRITICAL;
            } else if (OP_ADD_WARN_RESULT_FOR_TAGS.equals(actionName)) {
                newStatus =  Result.Status.WARN;
            } else {
                throw new MBeanException(
                        new UnsupportedOperationException(getClass().getSimpleName() + " does not support operation " + actionName));
            }
            
            status = newStatus.toString();
            registerDynamicHealthCheck(newStatus, tags.toArray(new String[tags.size()]));
            LOG.info("Activated JMX-adjustable Health Check with status "+newStatus+" and tags " + String.join(",", tags));
            return "Added check with result "+newStatus;

        }

        @Override
        public void setAttribute(final Attribute attribute)
                throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException,
                ReflectionException {
            throw new MBeanException(
                    new UnsupportedOperationException(getClass().getSimpleName() + " does not support setting attributes."));
        }

        @Override
        public AttributeList setAttributes(final AttributeList attributes) {
            return new AttributeList();
        }
    }

}
