/*
 *
 * 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.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.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.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<Class<? extends ConfiguredObject>, ConfiguredObject<?>> parents,
            final Map<String, Object> attributes,
            SystemConfig parent)
    {
        super(parents, 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));
        }

    }

    @Override
    protected void postResolveChildren()
    {
        super.postResolveChildren();
        if (_confidentialConfigurationEncryptionProvider != null)
        {
            updateEncrypter(_confidentialConfigurationEncryptionProvider);
        }
    }

    @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 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;
    }

    public EventLogger getEventLogger()
    {
        return _eventLogger;
    }

    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();
        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();
        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";
        }
    }
}
