/*
 * 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.document.util;

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

import org.apache.jackrabbit.oak.cache.CacheStats;
import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
import org.apache.jackrabbit.oak.plugins.document.Collection;
import org.apache.jackrabbit.oak.plugins.document.Document;
import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
import org.apache.jackrabbit.oak.plugins.document.DocumentStoreException;
import org.apache.jackrabbit.oak.plugins.document.UpdateOp;
import org.apache.jackrabbit.oak.plugins.document.cache.CacheInvalidationStats;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implements a <code>DocumentStore</code> wrapper and logs all calls.
 */
public class LoggingDocumentStoreWrapper implements DocumentStore {

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

    private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("ds.debug", "true"));

    private String logPrefix = "ds";

    final DocumentStore store;
    private boolean logThread;

    public LoggingDocumentStoreWrapper(DocumentStore store) {
        this.store = store;
    }

    public LoggingDocumentStoreWrapper(DocumentStore store, String prefix) {
        this.store = store;
        this.logPrefix = prefix;
    }

    public LoggingDocumentStoreWrapper withThreadNameLogging() {
        this.logThread = true;
        return this;
    }

    public LoggingDocumentStoreWrapper withPrefix(String prefix) {
        this.logPrefix = prefix;
        return this;
    }

    @Override
    public <T extends Document> T find(final Collection<T> collection,
                                       final String key) {
        try {
            logMethod("find", collection, key);
            return logResult(new Callable<T>() {
                @Override
                public T call() throws Exception {
                    return store.find(collection, key);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> T find(final Collection<T> collection,
                                       final String key,
                                       final int maxCacheAge) {
        try {
            logMethod("find", collection, key, maxCacheAge);
            return logResult(new Callable<T>() {
                @Override
                public T call() throws Exception {
                    return store.find(collection, key, maxCacheAge);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @NotNull
    @Override
    public <T extends Document> List<T> query(final Collection<T> collection,
                                final String fromKey,
                                final String toKey,
                                final int limit) {
        try {
            logMethod("query", collection, fromKey, toKey, limit);
            return logResult(new Callable<List<T>>() {
                @Override
                public List<T> call() throws Exception {
                    return store.query(collection, fromKey, toKey, limit);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    @NotNull
    public <T extends Document> List<T> query(final Collection<T> collection,
                                final String fromKey,
                                final String toKey,
                                final String indexedProperty,
                                final long startValue,
                                final int limit) {
        try {
            logMethod("query", collection, fromKey, toKey, indexedProperty, startValue, limit);
            return logResult(new Callable<List<T>>() {
                @Override
                public List<T> call() throws Exception {
                    return store.query(collection, fromKey, toKey, indexedProperty, startValue, limit);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> void remove(Collection<T> collection, String key) {
        try {
            logMethod("remove", collection, key);
            store.remove(collection, key);
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> void remove(Collection<T> collection, List<String> keys) {
        try {
            logMethod("remove", collection, keys);
            store.remove(collection, keys);
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> int remove(final Collection<T> collection,
                                           final Map<String, Long> toRemove) {
        try {
            logMethod("remove", collection, toRemove);
            return logResult(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return store.remove(collection, toRemove);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> int remove(final Collection<T> collection,
                                           final String indexedProperty, final long startValue, final long endValue)
            throws DocumentStoreException {
        try {
            logMethod("remove", collection, indexedProperty, startValue, endValue);
            return logResult(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return store.remove(collection, indexedProperty, startValue, endValue);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> boolean create(final Collection<T> collection,
                                               final List<UpdateOp> updateOps) {
        try {
            logMethod("create", collection, updateOps);
            return logResult(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return store.create(collection, updateOps);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> T createOrUpdate(final Collection<T> collection,
                                                 final UpdateOp update) {
        try {
            logMethod("createOrUpdate", collection, update);
            return logResult(new Callable<T>() {
                @Override
                public T call() throws Exception {
                    return store.createOrUpdate(collection, update);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> List<T> createOrUpdate(final Collection<T> collection,
                                                       final List<UpdateOp> updateOps) {
        try {
            logMethod("createOrUpdate", collection, updateOps);
            return logResult(new Callable<List<T>>() {
                @Override
                public List<T> call() throws Exception {
                    return store.createOrUpdate(collection, updateOps);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> T findAndUpdate(final Collection<T> collection,
                                                final UpdateOp update) {
        try {
            logMethod("findAndUpdate", collection, update);
            return logResult(new Callable<T>() {
                @Override
                public T call() throws Exception {
                    return store.findAndUpdate(collection, update);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public CacheInvalidationStats invalidateCache() {
        try {
            logMethod("invalidateCache");
            return store.invalidateCache();
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }
    
    @Override
    public CacheInvalidationStats invalidateCache(Iterable<String> keys) {
        try {
            logMethod("invalidateCache", keys);
            return store.invalidateCache(keys);
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> void invalidateCache(Collection<T> collection, String key) {
        try {
            logMethod("invalidateCache", collection, key);
            store.invalidateCache(collection, key);
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public void dispose() {
        try {
            logMethod("dispose");
            store.dispose();
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public <T extends Document> T getIfCached(final Collection<T> collection,
                                              final String key) {
        try {
            logMethod("getIfCached", collection, key);
            return logResult(new Callable<T>() {
                @Override
                public T call() throws Exception {
                    return store.getIfCached(collection, key);
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public void setReadWriteMode(String readWriteMode) {
        try {
            logMethod("setReadWriteMode", readWriteMode);
            store.setReadWriteMode(readWriteMode);
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public Iterable<CacheStats> getCacheStats() {
        try {
            logMethod("getCacheStats");
            return logResult(new Callable<Iterable<CacheStats>>() {
                @Override
                public Iterable<CacheStats> call() throws Exception {
                    return store.getCacheStats();
                }
            });
        } catch (Exception e) {
            logException(e);
            throw convert(e);
        }
    }

    @Override
    public Map<String, String> getMetadata() {
        return store.getMetadata();
    }

    @NotNull
    @Override
    public Map<String, String> getStats() {
        Map<String, String> result = store.getStats();
        logMethod("getStats", result);
        return result;
    }

    @Override
    public long determineServerTimeDifferenceMillis() {
        logMethod("determineServerTimeDifferenceMillis", "start");
        long result = store.determineServerTimeDifferenceMillis();
        logMethod("determineServerTimeDifferenceMillis", "end", result);
        return result;
    }

    private void logMethod(String methodName, Object... args) {
        StringBuilder buff = new StringBuilder(logPrefix);
        buff.append('.').append(methodName).append('(');
        for (int i = 0; i < args.length; i++) {
            if (i > 0) {
                buff.append(", ");
            }
            buff.append(quote(args[i]));
        }
        buff.append(");");
        log(buff.toString());
    }

    public static String quote(Object o) {
        if (o == null) {
            return "null";
        } else if (o instanceof String) {
            return JsopBuilder.encode((String) o);
        }
        return o.toString();
    }

    private RuntimeException convert(Exception e) {
        if (e instanceof RuntimeException) {
            return (RuntimeException) e;
        }
        log("// unexpected exception type: " + e.getClass().getName());
        return new DocumentStoreException("Unexpected exception: " + e.toString(), e);
    }

    private void logException(Exception e) {
        log("// exception: " + e.toString());
    }

    private <T> T logResult(Callable<T> callable) throws Exception {
        long time = System.nanoTime();
        T result = callable.call();
        time = System.nanoTime() - time;
        log("// " + (time / 1000) + " us\t" + quote(result));
        return result;
    }

    private void log(String message) {
        String out = this.logThread ? (Thread.currentThread() + " " + message) : message;
        if (DEBUG) {
            System.out.println(out);
        }
        LOG.info(out);
    }
}
