/*
 * 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.logging.log4j.server;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LogEventListener;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
import org.apache.logging.log4j.core.tools.BasicCommandLineArguments;
import org.apache.logging.log4j.core.tools.picocli.CommandLine.Option;
import org.apache.logging.log4j.core.util.Log4jThread;
import org.apache.logging.log4j.util.Strings;

/**
 * Abstract socket server for TCP and UDP implementations.
 *
 * @param <T>
 *            The kind of input stream read
 *
 *            TODO Make a LifeCycle
 */
public abstract class AbstractSocketServer<T extends InputStream> extends LogEventListener implements Runnable {

    protected static class CommandLineArguments extends BasicCommandLineArguments {

        @Option(names = { "--config", "-c" }, description = "Log4j configuration file location (path or URL).")
        private String configLocation;

        @Option(names = { "--interactive", "-i" }, description = "Accepts commands on standard input (\"exit\" is the only command).")
        private boolean interactive;

        @Option(names = { "--port", "-p" }, description = "The server port number, or 0 to automatically allocate a port number.")
        private int port;

        @Option(names = { "--localbindaddress", "-a" }, description = "Server socket local bind address.")
        private InetAddress localBindAddress;

        @Option(names = {"--classes", "-C"}, description = "Additional classes to allow deserialization")
        private List<String> allowedClasses;

        @Option(names = { "--wire-format", }, description = "Wire format, one of JSON, SERIALIZED, XML; defaults to JSON.")
        private WireFormat wireFormat = WireFormat.JSON;

        List<String> getAllowedClasses() {
            return allowedClasses == null ? Collections.<String>emptyList() : allowedClasses;
        }

        String getConfigLocation() {
            return configLocation;
        }

        boolean getInteractive() {
            return interactive;
        }

        InetAddress getLocalBindAddress() {
            return localBindAddress;
        }

        int getPort() {
            return port;
        }

        WireFormat getWireFormat() {
            return wireFormat;
        }

        void setAllowedClasses(final List<String> allowedClasses) {
            this.allowedClasses = allowedClasses;
        }

        void setConfigLocation(final String configLocation) {
            this.configLocation = configLocation;
        }

        void setInteractive(final boolean interactive) {
            this.interactive = interactive;
        }

        void setLocalBindAddress(final InetAddress localBindAddress) {
            this.localBindAddress = localBindAddress;
        }

        void setPort(final int port) {
            this.port = port;
        }

        void setWireFormat(final WireFormat wireFormat) {
            this.wireFormat = Objects.requireNonNull(wireFormat, "wireFormat");
        }
    }

    /**
     * Factory that creates a Configuration for the server.
     */
    protected static class ServerConfigurationFactory extends XmlConfigurationFactory {

        private final String path;

        public ServerConfigurationFactory(final String path) {
            this.path = path;
        }

        @Override
        public Configuration getConfiguration(final LoggerContext loggerContext, final String name,
                final URI configLocation) {
            if (Strings.isNotEmpty(path)) {
                File file = null;
                ConfigurationSource source = null;
                try {
                    file = new File(path);
                    final FileInputStream is = new FileInputStream(file);
                    source = new ConfigurationSource(is, file);
                } catch (final FileNotFoundException ignored) {
                    // Ignore this error
                }
                if (source == null) {
                    try {
                        final URL url = new URL(path);
                        source = new ConfigurationSource(url.openStream(), url);
                    } catch (final IOException ignored) {
                        // Ignore this error
                    }
                }

                try {
                    if (source != null) {
                        return new XmlConfiguration(loggerContext, source);
                    }
                } catch (final Exception ignored) {
                    // Ignore this error.
                }
                System.err.println("Unable to process configuration at " + path + ", using default.");
            }
            return super.getConfiguration(loggerContext, name, configLocation);
        }
    }

    protected static final int MAX_PORT = 65534;

    private volatile boolean active = true;

    protected final LogEventBridge<T> logEventInput;

    protected final Logger logger;

    /**
     * Creates a new socket server.
     *
     * @param port
     *            listen to this port
     * @param logEventInput
     *            Use this input to read log events.
     */
    public AbstractSocketServer(final int port, final LogEventBridge<T> logEventInput) {
        this.logger = LogManager.getLogger(this.getClass().getName() + '.' + port);
        this.logEventInput = Objects.requireNonNull(logEventInput, "LogEventInput");
    }

    public void awaitTermination(final Thread serverThread) throws Exception {
        final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            final String line = reader.readLine();
            if (line == null
                || line.equalsIgnoreCase("quit")
                || line.equalsIgnoreCase("stop")
                || line.equalsIgnoreCase("exit")) {
                this.shutdown();
                serverThread.join();
                break;
            }
        }
    }

    protected boolean isActive() {
        return this.active;
    }

    protected void setActive(final boolean isActive) {
        this.active = isActive;
    }

    public abstract void shutdown() throws Exception;

    /**
     * Start this server in a new thread.
     *
     * @return the new thread that running this server.
     */
    public Thread startNewThread() {
        final Thread thread = new Log4jThread(this);
        thread.start();
        return thread;
    }

}
