/*
 * 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.sling.commons.metrics.rrd4j.impl;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.ScheduledReporter;

import org.apache.felix.inventory.Format;
import org.apache.felix.inventory.InventoryPrinter;
import org.apache.felix.inventory.ZipAttachmentProvider;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static org.apache.sling.commons.metrics.rrd4j.impl.RRD4JReporter.DEFAULT_PATH;
import static org.apache.sling.commons.metrics.rrd4j.impl.RRD4JReporter.DEFAULT_STEP;

@Component(
        immediate = true,
        configurationPolicy = ConfigurationPolicy.REQUIRE,
        service = {InventoryPrinter.class, ZipAttachmentProvider.class},
        property = {
                InventoryPrinter.NAME + "=rrd4j-reporter",
                InventoryPrinter.TITLE + "=Sling Metrics RRD4J reporter",
                InventoryPrinter.FORMAT + "=TEXT"
        }
)
@Designate(ocd = CodahaleMetricsReporter.Configuration.class)
public class CodahaleMetricsReporter implements InventoryPrinter, ZipAttachmentProvider {

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

    private Configuration configuration;
    private File rrd;
    private ScheduledReporter reporter;

    private Map<String, CopyMetricRegistryListener> listeners = new ConcurrentHashMap<>();

    @ObjectClassDefinition(name = "Apache Sling Metrics reporter writing to RRD4J",
            description = "For syntax details on RRD data-source and round " +
                    "robin archive definitions see " +
                    "https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html and " +
                    "https://github.com/rrd4j/rrd4j/wiki/Tutorial. Changing " +
                    "any attribute in this configuration will replace an " +
                    "existing RRD file with a empty one!")
    public @interface Configuration {

        @AttributeDefinition(
                name = "Data sources",
                description = "RRDTool data source definitions " +
                        "(e.g. 'DS:oak_SESSION_LOGIN_COUNTER:COUNTER:300:0:U'). " +
                        "Replace colon characters in the metric name with an " +
                        "underscore!"
        )
        String[] datasources() default {};

        @AttributeDefinition(
                name = "Step",
                description = "The base interval in seconds with which data " +
                        "will be fed into the RRD"
        )
        int step() default DEFAULT_STEP;

        @AttributeDefinition(
                name = "Archives",
                description = "RRDTool round robin archive definitions. The " +
                        "default configuration defines four archives based " +
                        "on a default step of five seconds: " +
                        "1) per minute averages for six hours, " +
                        "2) per five minute averages 48 hours, " +
                        "3) per hour averages for four weeks, " +
                        "4) per day averages for one year."
        )
        String[] archives() default {
            "RRA:AVERAGE:0.5:12:360", "RRA:AVERAGE:0.5:60:576", "RRA:AVERAGE:0.5:720:336", "RRA:AVERAGE:0.5:17280:365"
        };

        @AttributeDefinition(
                name = "Path",
                description = "Path of the RRD file where metrics are stored. " +
                        "If the path is relative, it is resolved relative to " +
                        "the value of the framework property 'sling.home' when " +
                        "available, otherwise relative to the current working " +
                        "directory."
        )
        String path() default DEFAULT_PATH;
    }

    private MetricRegistry metricRegistry = new MetricRegistry();

    @Activate
    void activate(BundleContext context, Configuration config) throws Exception {
        LOG.info("Starting RRD4J Metrics reporter");
        configuration = config;
        rrd = getSafePath(context, config);
        reporter = RRD4JReporter.forRegistry(metricRegistry)
                .withPath(rrd)
                .withDatasources(config.datasources())
                .withArchives(config.archives())
                .withStep(config.step())
                .build();
        if (reporter != null) {
            reporter.start(config.step(), TimeUnit.SECONDS);
            LOG.info("Started RRD4J Metrics reporter: {}.", reporter);
        } else {
            LOG.warn("Illegal config will not start the RRD reporter. [path={}, datasources={}, archives={}, step={}].",
                    rrd.getPath(), config.datasources(), config.archives(), config.step());
        }
    }

    private static File getSafePath(BundleContext context, Configuration config) {
        String path = config.path();
        if (path == null || path.isEmpty()) {
            path = DEFAULT_PATH;
        }
        File rrd = new File(path);
        if (!rrd.isAbsolute()) {
            String home = context.getProperty("sling.home");
            if (home != null) {
                rrd = new File(home, rrd.getPath());
            }
        }
        return rrd;
    }

    @Deactivate
    void deactivate() {
        LOG.info("Stopping RRD4J Metrics reporter");
        if (reporter != null) {
            reporter.close();
            reporter = null;
        }
        configuration = null;
        rrd = null;
        LOG.info("Stopped RRD4J Metrics reporter");
    }

    @Reference(
            service = MetricRegistry.class,
            cardinality = ReferenceCardinality.MULTIPLE,
            policy = ReferencePolicy.DYNAMIC)
    synchronized void addMetricRegistry(MetricRegistry metricRegistry,
                                        Map<String, Object> properties) {
        String name = (String) properties.get("name");
        if (name == null) {
            name = metricRegistry.toString();
        }
        CopyMetricRegistryListener listener = new CopyMetricRegistryListener(this.metricRegistry, name);
        listener.start(metricRegistry);
        this.listeners.put(name, listener);
        LOG.info("Bound Metrics Registry {} ",name);
    }

    synchronized void removeMetricRegistry(MetricRegistry metricRegistry,
                                           Map<String, Object> properties) {
        String name = (String) properties.get("name");
        if (name == null) {
            name = metricRegistry.toString();
        }
        CopyMetricRegistryListener metricRegistryListener = listeners.get(name);
        if ( metricRegistryListener != null) {
            metricRegistryListener.stop(metricRegistry);
            this.listeners.remove(name);
        }
        LOG.info("Unbound Metrics Registry {} ",name);
    }

    //------------------------< InventoryPrinter >------------------------------

    @Override
    public void print(PrintWriter pw, Format format, boolean isZip) {
        if (format == Format.TEXT) {
            pw.println("Sling Metrics RRD4J reporter");
            pw.println("Path: " + rrd.getAbsolutePath());
            pw.println("Step: " + configuration.step());
            pw.println("Datasources: " + Arrays.asList(configuration.datasources()));
            pw.println("Archives: " + Arrays.asList(configuration.archives()));
        }
    }

    //----------------------< ZipAttachmentProvider >---------------------------

    @Override
    public void addAttachments(ZipOutputStream zos, String namePrefix)
            throws IOException {
        if (rrd.exists()) {
            appendFile(zos, rrd, namePrefix + configuration.path());
        }
        File props = new File(rrd.getParentFile(), rrd.getName() + ".properties");
        if (props.exists()) {
            appendFile(zos, props, namePrefix + configuration.path() + ".properties");
        }
    }

    private void appendFile(ZipOutputStream zos, File file, String name)
            throws IOException {
        ZipEntry entry = new ZipEntry(name);
        entry.setSize(file.length());
        zos.putNextEntry(entry);
        try {
            Files.copy(file.toPath(), zos);
            zos.flush();
        } finally {
            zos.closeEntry();
        }
    }
}
