/*
 * 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.sling.installer.hc;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.hc.annotations.SlingHealthCheck;
import org.apache.sling.hc.api.HealthCheck;
import org.apache.sling.hc.api.Result;
import org.apache.sling.hc.util.FormattingResultLog;
import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.info.InfoProvider;
import org.apache.sling.installer.api.info.InstallationState;
import org.apache.sling.installer.api.info.Resource;
import org.apache.sling.installer.api.info.ResourceGroup;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SlingHealthCheck(
    name = OsgiInstallerHealthCheck.HC_NAME,
    description = "Checks that all OSGi configurations/bundles are successfully installed by the OSGi Installer (and are not skipped for some reason).",
    tags = {
        "installer",
        "osgi"
    }
)
public class OsgiInstallerHealthCheck implements HealthCheck {
    protected static final String HC_NAME = "OSGi Installer Health Check";

    @Reference
    private InfoProvider infoProvider;

    private static final Logger LOG = LoggerFactory.getLogger(OsgiInstallerHealthCheck.class);

    private static final String DEFAULT_URL_PREFIX = "jcrinstall:/apps/";

    @Property(label = "URL Prefixes to consider", description = "Only those OSGi configurations/bundles whose location are starting with one of the given URL prefixes are checked (whether they are installed correctly). Open /system/console/osgi-installer for a list of valid prefixes.", cardinality = 1, value = DEFAULT_URL_PREFIX)
    static final String PROP_URL_PREFIXES = "urlPrefixes";

    @Property(label = "Check Bundles", description = "If enabled bundles are checked (restricted to the ones matching one of the prefixes)", boolValue = true)
    static final String PROP_CHECK_BUNDLES = "checkBundles";

    @Property(label = "Check Configurations", description = "If enabled configurations are checked (restricted to the ones matching one of the prefixes)", boolValue = true)
    static final String PROP_CHECK_CONFIGURATIONS = "checkConfigurations";

    private String[] urlPrefixes;
    private boolean checkBundles;
    private boolean checkConfigurations;
    
    private final static String DOCUMENTATION_URL = "https://sling.apache.org/documentation/bundles/osgi-installer.html#health-check";

    @Reference
    private ConfigurationAdmin configurationAdmin;

    @Activate
    public void activate(Map<String, ?> properties) {
        urlPrefixes = PropertiesUtil.toStringArray(properties.get(PROP_URL_PREFIXES),
                new String[] { DEFAULT_URL_PREFIX });
        checkBundles = PropertiesUtil.toBoolean(properties.get(PROP_CHECK_BUNDLES), true);
        checkConfigurations = PropertiesUtil.toBoolean(properties.get(PROP_CHECK_CONFIGURATIONS), true);
    }

    @Override
    public Result execute() {
        InstallationState installationState = infoProvider.getInstallationState();
        FormattingResultLog hcLog = new FormattingResultLog();

        int numCheckedConfigurations = 0;
        int numCheckedBundles = 0;
        // go through all resource groups of the OSGi Installer
        for (final ResourceGroup group : installationState.getInstalledResources()) {
            String type = evaluateGroup(group, hcLog);
            switch (type) {
            case InstallableResource.TYPE_CONFIG:
                numCheckedConfigurations++;
                break;
            case InstallableResource.TYPE_BUNDLE:
                numCheckedBundles++;
                break;
            }
        }
        hcLog.info("Checked {} OSGi bundles and {} configurations.", numCheckedBundles, numCheckedConfigurations);
        if (hcLog.getAggregateStatus().ordinal() >= Result.Status.WARN.ordinal()) {
            hcLog.info("Refer to the OSGi installer's documentation page at {} for further details on how to fix those issues.", DOCUMENTATION_URL);
        }
        return new Result(hcLog);
    }

    /**
     * @param group
     *            the resource group to evaluate
     * @param hcLog
     *            the log to fill during the health check
     * @return the type of resources in this group ("bundle" or "config") or empty string, if the group was not
     *         considered by this health check
     */
    private String evaluateGroup(ResourceGroup group, FormattingResultLog hcLog) {
        Resource invalidResource = null;
        String resourceType = "";
        // go through all resources within the given group
        for (Resource resource : group.getResources()) {
            // check for the correct type
            resourceType = resource.getType();
            switch (resourceType) {
            case InstallableResource.TYPE_CONFIG:
                if (!checkConfigurations) {
                    LOG.debug("Skip resource '{}', configuration checks are disabled", resource.getEntityId());
                    return "";
                }
                break;
            case InstallableResource.TYPE_BUNDLE:
                if (!checkBundles) {
                    LOG.debug("Skip resource '{}', bundle checks are disabled", resource.getEntityId());
                    return "";
                }
                break;
            default:
                LOG.debug("Skip resource '{}' as it is neither a bundle nor a configuration but a {}",
                        resource.getEntityId(), resourceType);
                return "";
            }
            if (StringUtils.startsWithAny(resource.getURL(), urlPrefixes)) {
                switch (resource.getState()) {
                case IGNORED: // means a considered resource was found and it is invalid
                    // still the other resources need to be evaluated
                case INSTALL:
                    if (invalidResource == null) {
                        invalidResource = resource;
                    }
                    break;
                default:
                    // means a considered resource was found and it is valid
                    // no need to evaluate other resources from this group
                    return resourceType;
                }
            } else {
                LOG.debug("Skipping resource '{}' as its URL is not starting with any of these prefixes'{}'", resource,
                        StringUtils.join(urlPrefixes, ","));
            }
        }
        if (invalidResource != null) {
            if (resourceType.equals(InstallableResource.TYPE_CONFIG)) {
                hcLog.critical(
                        "The installer state of the OSGi configuration resource '{}' is {}, config might have been manually overwritten!",
                        invalidResource, invalidResource.getState());
            } else {
                hcLog.critical(
                        "The installer state of the OSGi bundle resource '{}' is {}, probably because a later or the same version of that bundle is already installed!",
                        invalidResource, invalidResource.getState());
            }
            return resourceType;
        } else {
            return ""; // do not count this group, as only non-considered resources have been in there
        }
        
    }

}
