/*
 *
 * 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.qpid.server.model;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.management.BufferPoolMXBean;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.PlatformManagedObject;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.configuration.CommonProperties;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.messages.BrokerMessages;
import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory;
import org.apache.qpid.server.plugin.PluggableFactoryLoader;
import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.util.HousekeepingExecutor;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.apache.qpid.server.util.SystemUtils;

public abstract class AbstractContainer<X extends AbstractContainer<X>> extends AbstractConfiguredObject<X> implements Container<X>
{
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractContainer.class);

    private final BufferPoolMXBean _bufferPoolMXBean;
    private final List<String> _jvmArguments;
    private final long _maximumHeapSize = Runtime.getRuntime().maxMemory();
    private final long _maximumDirectMemorySize = getMaxDirectMemorySize();
    protected SystemConfig<?> _parent;
    protected EventLogger _eventLogger;

    @ManagedAttributeField(beforeSet = "preEncrypterProviderSet", afterSet = "postEncrypterProviderSet")
    private String _confidentialConfigurationEncryptionProvider;

    protected HousekeepingExecutor _houseKeepingTaskExecutor;

    @ManagedAttributeField
    private int _housekeepingThreadCount;

    private String _preConfidentialConfigurationEncryptionProvider;

    AbstractContainer(
            final Map<String, Object> attributes,
            SystemConfig parent)
    {
        super(parent, attributes);
        _parent = parent;
        _eventLogger = parent.getEventLogger();
        _jvmArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
        BufferPoolMXBean bufferPoolMXBean = null;
        List<BufferPoolMXBean> bufferPoolMXBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
        for(BufferPoolMXBean mBean : bufferPoolMXBeans)
        {
            if (mBean.getName().equals("direct"))
            {
                bufferPoolMXBean = mBean;
                break;
            }
        }
        _bufferPoolMXBean = bufferPoolMXBean;
        if(attributes.get(CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER) != null )
        {
            _confidentialConfigurationEncryptionProvider =
                    String.valueOf(attributes.get(CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER));

            // resolve context attributes here
            // as encrypter factory relies on context variables
            onResolve();
            updateEncrypter(_confidentialConfigurationEncryptionProvider);
        }

    }

    @Override
    protected void postResolveChildren()
    {
        super.postResolveChildren();
    }

    @SuppressWarnings("unused")
    public static Collection<String> getAvailableConfigurationEncrypters()
    {
        return (new QpidServiceLoader()).getInstancesByType(ConfigurationSecretEncrypterFactory.class).keySet();
    }

    static long getMaxDirectMemorySize()
    {
        long maxMemory = 0;
        try
        {
            ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
            Class<?> hotSpotDiagnosticMXBeanClass = Class.forName("com.sun.management.HotSpotDiagnosticMXBean", true, systemClassLoader);
            Class<?> vmOptionClass = Class.forName("com.sun.management.VMOption", true, systemClassLoader);

            Object hotSpotDiagnosticMXBean = ManagementFactory.getPlatformMXBean((Class<? extends PlatformManagedObject>)hotSpotDiagnosticMXBeanClass);
            Method getVMOption = hotSpotDiagnosticMXBeanClass.getDeclaredMethod("getVMOption", String.class);
            Object vmOption = getVMOption.invoke(hotSpotDiagnosticMXBean, "MaxDirectMemorySize");
            Method getValue = vmOptionClass.getDeclaredMethod("getValue");
            String maxDirectMemoryAsString = (String)getValue.invoke(vmOption);
            maxMemory = Long.parseLong(maxDirectMemoryAsString);
        }
        catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException e)
        {
            LOGGER.debug("Cannot determine direct memory max size using com.sun.management.HotSpotDiagnosticMXBean: " + e.getMessage());
        }
        catch (InvocationTargetException e)
        {
            throw new ServerScopedRuntimeException("Unexpected exception in evaluation of MaxDirectMemorySize with HotSpotDiagnosticMXBean", e.getTargetException());
        }

        if (maxMemory == 0)
        {
            Pattern
                    maxDirectMemorySizeArgumentPattern = Pattern.compile("^\\s*-XX:MaxDirectMemorySize\\s*=\\s*(\\d+)\\s*([KkMmGgTt]?)\\s*$");
            RuntimeMXBean RuntimemxBean = ManagementFactory.getRuntimeMXBean();
            List<String> inputArguments = RuntimemxBean.getInputArguments();
            boolean argumentFound = false;
            for (String argument : inputArguments)
            {
                Matcher matcher = maxDirectMemorySizeArgumentPattern.matcher(argument);
                if (matcher.matches())
                {
                    argumentFound = true;
                    maxMemory = Long.parseLong(matcher.group(1));
                    String unit = matcher.group(2);
                    char unitChar = "".equals(unit) ? 0 : unit.charAt(0);
                    switch (unitChar)
                    {
                        case 'k':
                        case 'K':
                            maxMemory *= 1024l;
                            break;
                        case 'm':
                        case 'M':
                            maxMemory *= 1024l * 1024l;
                            break;
                        case 'g':
                        case 'G':
                            maxMemory *= 1024l * 1024l * 1024l;
                            break;
                        case 't':
                        case 'T':
                            maxMemory *= 1024l * 1024l * 1024l * 1024l;
                            break;
                        case 0:
                            // noop
                            break;
                        default:
                            throw new IllegalStateException("Unexpected unit character in MaxDirectMemorySize argument : " + argument);
                    }
                    // do not break; continue. Oracle and IBM JVMs use the last value when argument is specified multiple times
                }
            }

            if (maxMemory == 0)
            {
                if (argumentFound)
                {
                    throw new IllegalArgumentException("Qpid Broker cannot operate with 0 direct memory. Please, set JVM argument MaxDirectMemorySize to non-zero value");
                }
                else
                {
                    maxMemory = Runtime.getRuntime().maxMemory();
                }
            }
        }

        return maxMemory;
    }

    private void updateEncrypter(final String encryptionProviderType)
    {
        if(encryptionProviderType != null && !"".equals(encryptionProviderType.trim()))
        {
            PluggableFactoryLoader<ConfigurationSecretEncrypterFactory> factoryLoader =
                    new PluggableFactoryLoader<>(ConfigurationSecretEncrypterFactory.class);
            ConfigurationSecretEncrypterFactory factory = factoryLoader.get(encryptionProviderType);
            if (factory == null)
            {
                throw new IllegalConfigurationException("Unknown Configuration Secret Encryption method "
                                                        + encryptionProviderType);
            }
            setEncrypter(factory.createEncrypter(this));
        }
        else
        {
            setEncrypter(null);
        }
    }

    public String getBuildVersion()
    {
        return CommonProperties.getBuildVersion();
    }

    public String getOperatingSystem()
    {
        return SystemUtils.getOSString();
    }

    public String getPlatform()
    {
        return System.getProperty("java.vendor") + " "
                      + System.getProperty("java.runtime.version", System.getProperty("java.version"));
    }

    public String getProcessPid()
    {
        return SystemUtils.getProcessPid();
    }

    public String getProductVersion()
    {
        return CommonProperties.getReleaseVersion();
    }

    public int getNumberOfCores()
    {
        return Runtime.getRuntime().availableProcessors();
    }

    public String getConfidentialConfigurationEncryptionProvider()
    {
        return _confidentialConfigurationEncryptionProvider;
    }

    public int getHousekeepingThreadCount()
    {
        return _housekeepingThreadCount;
    }

    public String getModelVersion()
    {
        return BrokerModel.MODEL_VERSION;
    }

    @Override
    public EventLogger getEventLogger()
    {
        return _eventLogger;
    }

    @Override
    public void setEventLogger(final EventLogger eventLogger)
    {
        _eventLogger = eventLogger;
    }

    @SuppressWarnings("unused")
    private void preEncrypterProviderSet()
    {
        _preConfidentialConfigurationEncryptionProvider = _confidentialConfigurationEncryptionProvider;
    }

    @SuppressWarnings("unused")
    private void postEncrypterProviderSet()
    {
        if (!Objects.equals(_preConfidentialConfigurationEncryptionProvider,
                            _confidentialConfigurationEncryptionProvider))
        {
            updateEncrypter(_confidentialConfigurationEncryptionProvider);
            forceUpdateAllSecureAttributes();
        }
    }

    public int getNumberOfLiveThreads()
    {
        return ManagementFactory.getThreadMXBean().getThreadCount();
    }

    public long getMaximumHeapMemorySize()
    {
        return _maximumHeapSize;
    }

    public long getUsedHeapMemorySize()
    {
        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    }

    public long getMaximumDirectMemorySize()
    {
        return _maximumDirectMemorySize;
    }

    public long getUsedDirectMemorySize()
    {
        if (_bufferPoolMXBean == null)
        {
            return -1;
        }
        return _bufferPoolMXBean.getMemoryUsed();
    }

    public long getDirectMemoryTotalCapacity()
    {
        if (_bufferPoolMXBean == null)
        {
            return -1;
        }
        return _bufferPoolMXBean.getTotalCapacity();
    }

    public int getNumberOfObjectsPendingFinalization()
    {
        return ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount();
    }

    public List<String> getJvmArguments()
    {
        return _jvmArguments;
    }

    public void performGC()
    {
        getEventLogger().message(BrokerMessages.OPERATION("performGC"));
        System.gc();
    }

    public Content getThreadStackTraces(boolean appendToLog)
    {
        getEventLogger().message(BrokerMessages.OPERATION("getThreadStackTraces"));
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true);
        StringBuilder threadDump = new StringBuilder();
        threadDump.append(String.format("Full thread dump captured %s", Instant.now())).append(System.lineSeparator());

        for (ThreadInfo threadInfo : threadInfos)
        {
            threadDump.append(getThreadStackTraces(threadInfo));
        }
        long[] deadLocks = threadMXBean.findDeadlockedThreads();
        if (deadLocks != null && deadLocks.length > 0)
        {
            ThreadInfo[] deadlockedThreads = threadMXBean.getThreadInfo(deadLocks);
            threadDump.append(System.lineSeparator()).append("Deadlock is detected!").append(System.lineSeparator());
            for (ThreadInfo threadInfo : deadlockedThreads)
            {
                threadDump.append(getThreadStackTraces(threadInfo));
            }
        }
        String threadStackTraces = threadDump.toString();
        if (appendToLog)
        {
            LOGGER.warn("Thread dump:{} {}", System.lineSeparator(), threadStackTraces);
        }
        return new ThreadStackContent(threadStackTraces);
    }

    public Content findThreadStackTraces(String threadNameFindExpression)
    {
        getEventLogger().message(BrokerMessages.OPERATION("findThreadStackTraces"));
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true);
        StringBuilder threadDump = new StringBuilder();
        threadDump.append(String.format("Thread dump (names matching '%s') captured %s",
                                        threadNameFindExpression,
                                        Instant.now())).append(System.lineSeparator());

        Pattern pattern = threadNameFindExpression == null || threadNameFindExpression.equals("") ? null : Pattern.compile(
                threadNameFindExpression);
        for (ThreadInfo threadInfo : threadInfos)
        {
            if (pattern == null || pattern.matcher(threadInfo.getThreadName()).find())
            {
                threadDump.append(getThreadStackTraces(threadInfo));
            }
        }
        return new ThreadStackContent(threadDump.toString());
    }

    private String getThreadStackTraces(final ThreadInfo threadInfo)
    {
        String lineSeparator = System.lineSeparator();
        StringBuilder dump = new StringBuilder();
        dump.append("\"").append(threadInfo.getThreadName()).append("\"").append(" Id=")
            .append(threadInfo.getThreadId()).append( " ").append(threadInfo.getThreadState());
        if (threadInfo.getLockName() != null)
        {
            dump.append(" on ").append(threadInfo.getLockName());
        }
        if (threadInfo.getLockOwnerName() != null)
        {
            dump.append(" owned by \"").append(threadInfo.getLockOwnerName())
                .append("\" Id=").append(threadInfo.getLockOwnerId());
        }
        if (threadInfo.isSuspended())
        {
            dump.append(" (suspended)");
        }
        if (threadInfo.isInNative())
        {
            dump.append(" (in native)");
        }
        dump.append(lineSeparator);
        StackTraceElement[] stackTrace = threadInfo.getStackTrace();
        for (int i = 0; i < stackTrace.length; i++)
        {
            StackTraceElement stackTraceElement = stackTrace[i];
            dump.append("    at ").append(stackTraceElement.toString()).append(lineSeparator);

            LockInfo lockInfo = threadInfo.getLockInfo();
            if (i == 0 && lockInfo != null)
            {
                Thread.State threadState = threadInfo.getThreadState();
                switch (threadState)
                {
                    case BLOCKED:
                        dump.append("    -  blocked on ").append(lockInfo).append(lineSeparator);
                        break;
                    case WAITING:
                        dump.append("    -  waiting on ").append(lockInfo).append(lineSeparator);
                        break;
                    case TIMED_WAITING:
                        dump.append("    -  waiting on ").append(lockInfo).append(lineSeparator);
                        break;
                    default:
                }
            }

            for (MonitorInfo mi : threadInfo.getLockedMonitors())
            {
                if (mi.getLockedStackDepth() == i)
                {
                    dump.append("    -  locked ").append(mi).append(lineSeparator);
                }
            }
        }

        LockInfo[] locks = threadInfo.getLockedSynchronizers();
        if (locks.length > 0)
        {
            dump.append(lineSeparator).append("    Number of locked synchronizers = ").append(locks.length);
            dump.append(lineSeparator);
            for (LockInfo li : locks)
            {
                dump.append("    - " + li);
                dump.append(lineSeparator);
            }
        }
        dump.append(lineSeparator);
        return dump.toString();
    }

    public ScheduledFuture<?> scheduleHouseKeepingTask(long period, final TimeUnit unit, Runnable task)
    {
        return _houseKeepingTaskExecutor.scheduleAtFixedRate(task, period / 2, period, unit);
    }

    public ScheduledFuture<?> scheduleTask(long delay, final TimeUnit unit, Runnable task)
    {
        return _houseKeepingTaskExecutor.schedule(task, delay, unit);
    }

    public static class ThreadStackContent implements Content, CustomRestHeaders
    {
        private final String _threadStackTraces;

        public ThreadStackContent(final String threadStackTraces)
        {
            _threadStackTraces = threadStackTraces;
        }

        @Override
        public void write(final OutputStream outputStream) throws IOException
        {
            if (_threadStackTraces != null)
            {
                outputStream.write(_threadStackTraces.getBytes(Charset.forName("UTF-8")));
            }
        }

        @Override
        public void release()
        {
            // noop; nothing to release
        }

        @RestContentHeader("Content-Type")
        public String getContentType()
        {
            return "text/plain;charset=utf-8";
        }
    }
}
