/*
 * 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.jackrabbit.oak.plugins.blob;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.System.nanoTime;
import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount;
import static org.apache.jackrabbit.oak.commons.jmx.ManagementOperation.Status.formatTime;
import static org.apache.jackrabbit.oak.commons.jmx.ManagementOperation.done;
import static org.apache.jackrabbit.oak.commons.jmx.ManagementOperation.newManagementOperation;

import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;

import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;

import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean;
import org.apache.jackrabbit.oak.commons.jmx.ManagementOperation;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Default implementation of {@link BlobGCMBean} based on a {@link BlobGarbageCollector}.
 */
public class  BlobGC extends AnnotatedStandardMBean implements BlobGCMBean {
    private static final Logger log = LoggerFactory.getLogger(BlobGC.class);

    public static final String OP_NAME = "Blob garbage collection";

    private final BlobGarbageCollector blobGarbageCollector;
    private final Executor executor;

    private ManagementOperation<String> gcOp = done(OP_NAME, "");
    
    public static final String CONSISTENCY_OP_NAME = "Blob consistency check";
    
    private ManagementOperation<String> consistencyOp = done(CONSISTENCY_OP_NAME, "");
    
    /**
     * @param blobGarbageCollector  Blob garbage collector
     * @param executor              executor for running the garbage collection task
     */
    public BlobGC(
            @NotNull BlobGarbageCollector blobGarbageCollector,
            @NotNull Executor executor) {
        super(BlobGCMBean.class);
        this.blobGarbageCollector = checkNotNull(blobGarbageCollector);
        this.executor = checkNotNull(executor);
    }

    @NotNull
    @Override
    public CompositeData startBlobGC(final boolean markOnly) {
        if (gcOp.isDone()) {
            gcOp = newManagementOperation(OP_NAME, new Callable<String>() {
                @Override
                public String call() throws Exception {
                    long t0 = nanoTime();
                    blobGarbageCollector.collectGarbage(markOnly);
                    return "Blob gc completed in " + formatTime(nanoTime() - t0);
                }
            });
            executor.execute(gcOp);
        }
        return getBlobGCStatus();
    }

    @Override
    public CompositeData startBlobGC(final boolean markOnly, final boolean forceBlobIdRetrieve) {
        if (gcOp.isDone()) {
            gcOp = newManagementOperation(OP_NAME, new Callable<String>() {
                @Override
                public String call() throws Exception {
                    long t0 = nanoTime();
                    blobGarbageCollector.collectGarbage(markOnly, forceBlobIdRetrieve);
                    return "Blob gc completed in " + formatTime(nanoTime() - t0);
                }
            });
            executor.execute(gcOp);
        }
        return getBlobGCStatus();
    }

    @NotNull
    @Override
    public CompositeData getBlobGCStatus() {
        return gcOp.getStatus().toCompositeData();
    }


    @Override
    public CompositeData checkConsistency() {
        if (consistencyOp.isDone()) {
            consistencyOp = newManagementOperation(CONSISTENCY_OP_NAME, new Callable<String>() {
                @Override
                public String call() throws Exception {
                    long t0 = nanoTime();
                    long missing = blobGarbageCollector.checkConsistency();
                    return "Consistency check completed in "
                        + formatTime(nanoTime() - t0) + ". " +
                        + missing + " missing blobs found (details in the log).";
                }
            });
            executor.execute(consistencyOp);
        }
        return getConsistencyCheckStatus();
    }

    @NotNull
    @Override
    public CompositeData getConsistencyCheckStatus() {
        return consistencyOp.getStatus().toCompositeData();
    }

    @Override 
    public TabularData getGlobalMarkStats() {
        TabularDataSupport tds;
        try {
            TabularType tt = new TabularType(BlobGC.class.getName(),
                                                "Garbage collection global mark phase Stats", MARK_TYPE,
                                                new String[] {"repositoryId"});
            tds = new TabularDataSupport(tt);           
            List<GarbageCollectionRepoStats> stats = blobGarbageCollector.getStats();
            for (GarbageCollectionRepoStats stat : stats) {
                tds.put(toCompositeData(stat));
            }
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
        return tds;
    }

    private CompositeDataSupport toCompositeData(GarbageCollectionRepoStats statObj) throws OpenDataException {
        Object[] values = new Object[] {
                statObj.getRepositoryId() + (statObj.isLocal() ? " *" : ""),
                (statObj.getStartTime() == 0 ? "" : (new Date(statObj.getStartTime()))).toString(),
                (statObj.getEndTime() == 0 ? "" : (new Date(statObj.getEndTime()))).toString(),
                statObj.getLength(),
                humanReadableByteCount(statObj.getLength()),
                statObj.getNumLines()
        };
        return new CompositeDataSupport(MARK_TYPE, MARK_FIELD_NAMES, values);
    }
    
    private static final String[] MARK_FIELD_NAMES = new String[] {
            "repositoryId",
            "markStartTime",
            "markEndTime",
            "referenceFileSizeBytes",
            "referencesFileSize",
            "numReferences",
    };
    
    private static final String[] MARK_FIELD_DESCRIPTIONS = new String[] {
           "Repository ID",
           "Start time of mark",
           "End time of mark",
           "References file size in bytes",
           "References file size in human readable format",
           "Number of references"
    };
    
    private static final OpenType[] MARK_FIELD_TYPES = new OpenType[] {
            SimpleType.STRING,
            SimpleType.STRING,
            SimpleType.STRING,
            SimpleType.LONG,
            SimpleType.STRING,
            SimpleType.INTEGER
    };
    
    private static final CompositeType MARK_TYPE = createMarkCompositeType();
    
    private static CompositeType createMarkCompositeType() {
        try {
            return new CompositeType(
                    GarbageCollectionRepoStats.class.getName(),
                    "Composite data type for datastore GC statistics", MARK_FIELD_NAMES, MARK_FIELD_DESCRIPTIONS,
                MARK_FIELD_TYPES);
        } catch (OpenDataException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public TabularData getOperationStats() {
        TabularDataSupport tds;
        try {
            TabularType tt = new TabularType(BlobGC.class.getName(),
                "Garbage Collection Operation Stats", OP_STATS_TYPE,
                OP_STATS_FIELD_NAMES);
            tds = new TabularDataSupport(tt);
            OperationsStatsMBean operationStats = blobGarbageCollector.getOperationStats();
            tds.put(toCompositeData(operationStats));
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
        return tds;
    }

    private CompositeData toCompositeData(OperationsStatsMBean statObj) throws OpenDataException {
        Object[] values = new Object[] {
            statObj.getStartCount(),
            statObj.getFailureCount(),
            statObj.duration()
        };
        return new CompositeDataSupport(OP_STATS_TYPE, OP_STATS_FIELD_NAMES, values);
    }

    private static final String[] OP_STATS_FIELD_NAMES = new String[] {
        "count",
        "failureCount",
        "duration"
    };

    private static final String[] OP_STATS_FIELD_DESCRIPTIONS = new String[] {
        "Count",
        "Failure Count",
        "Duration"
    };

    private static final OpenType[] OP_STATS_FIELD_TYPES = new OpenType[] {
        SimpleType.LONG,
        SimpleType.LONG,
        SimpleType.LONG
    };

    private static final CompositeType OP_STATS_TYPE = createOpStatsCompositeType();

    private static CompositeType createOpStatsCompositeType() {
        try {
            return new CompositeType(
                GarbageCollectionRepoStats.class.getName(),
                "Composite data type for datastore GC operation stats", OP_STATS_FIELD_NAMES, OP_STATS_FIELD_DESCRIPTIONS,
                OP_STATS_FIELD_TYPES);
        } catch (OpenDataException e) {
            throw new IllegalStateException(e);
        }
    }
}
