// 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.cloudstack.syslog;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.net.SyslogAppender;
import org.apache.log4j.spi.LoggingEvent;

import com.cloud.utils.net.NetUtils;

public class AlertsSyslogAppender extends AppenderSkeleton {
    String _syslogHosts = null;
    String _delimiter = ",";
    List<String> _syslogHostsList = null;
    List<SyslogAppender> _syslogAppenders = null;
    private String _facility;
    private String _pairDelimiter = "//";
    private String _keyValueDelimiter = "::";
    private int alertType = -1;
    private long dataCenterId = 0;
    private long podId = 0;
    private long clusterId = 0;
    private String sysMessage = null;
    public static final int LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER = 9;
    public static final int LENGTH_OF_STRING_MESSAGE = 8;
    public static final String MESSAGE_DELIMITER_STRING = "   ";
    //add the alertType in this array it its level needs to be set to critical
    private static final int[] criticalAlerts = {7, 8, 9, 10, 11, 12, 13, 15, 16, 19, 20, 27};
    private static final Map<Integer, String> alertsMap;

    static {
        Map<Integer, String> aMap = new HashMap<Integer, String>(27);
        aMap.put(0, "availableMemory");
        aMap.put(1, "availableCpu");
        aMap.put(2, "availableStorage");
        aMap.put(3, "remainingStorageAllocated");
        aMap.put(4, "unallocatedVirtualNetworkpublicIp");
        aMap.put(5, "unallocatedPrivateIp");
        aMap.put(6, "availableSecondaryStorage");
        aMap.put(7, "host");
        aMap.put(8, "userVmState");
        aMap.put(9, "domainRouterVmState ");
        aMap.put(10, "consoleProxyVmState");
        aMap.put(11, "routingConnection");
        aMap.put(12, "storageIssueSystemVms");
        aMap.put(13, "usageServerStatus");
        aMap.put(14, "managementNode");
        aMap.put(15, "domainRouterMigrate");
        aMap.put(16, "consoleProxyMigrate");
        aMap.put(17, "userVmMigrate");
        aMap.put(18, "unallocatedVlan");
        aMap.put(19, "ssvmStopped");
        aMap.put(20, "usageServerResult");
        aMap.put(21, "storageDelete");
        aMap.put(22, "updateResourceCount");
        aMap.put(23, "usageSanityResult");
        aMap.put(24, "unallocatedDirectAttachedPublicIp");
        aMap.put(25, "unallocatedLocalStorage");
        aMap.put(26, "resourceLimitExceeded");
        aMap.put(27, "sync");

        alertsMap = Collections.unmodifiableMap(aMap);
    }

    @Override
    protected void append(LoggingEvent event) {
        if (!isAsSevereAsThreshold(event.getLevel())) {
            return;
        }

        if (_syslogAppenders != null && !_syslogAppenders.isEmpty()) {
            try {
                String logMessage = event.getRenderedMessage();
                if (logMessage.contains("alertType") && logMessage.contains("message")) {
                    parseMessage(logMessage);
                    String syslogMessage = createSyslogMessage();

                    LoggingEvent syslogEvent = new LoggingEvent(event.getFQNOfLoggerClass(), event.getLogger(), event.getLevel(), syslogMessage, null);

                    for (SyslogAppender syslogAppender : _syslogAppenders) {
                        syslogAppender.append(syslogEvent);
                    }
                }
            } catch (Exception e) {
                errorHandler.error(e.getMessage());
            }
        }
    }

    @Override
    synchronized public void close() {
        for (SyslogAppender syslogAppender : _syslogAppenders) {
            syslogAppender.close();
        }
    }

    @Override
    public boolean requiresLayout() {
        return true;
    }

    void setSyslogAppenders() {
        if (_syslogAppenders == null) {
            _syslogAppenders = new ArrayList<SyslogAppender>();
        }

        if (_syslogHosts == null || _syslogHosts.trim().isEmpty()) {
            reset();
            return;
        }

        _syslogHostsList = parseSyslogHosts(_syslogHosts);

        if (!validateIpAddresses()) {
            reset();
            errorHandler.error(" Invalid format for the IP Addresses parameter ");
            return;
        }

        for (String syslogHost : _syslogHostsList) {
            _syslogAppenders.add(new SyslogAppender(getLayout(), syslogHost, SyslogAppender.getFacility(_facility)));
        }
    }

    private List<String> parseSyslogHosts(String syslogHosts) {
        List<String> result = new ArrayList<String>();

        final StringTokenizer tokenizer = new StringTokenizer(syslogHosts, _delimiter);
        while (tokenizer.hasMoreTokens()) {
            result.add(tokenizer.nextToken().trim());
        }
        return result;
    }

    private boolean validateIpAddresses() {
        for (String ipAddress : _syslogHostsList) {
            String[] hostTokens = (ipAddress.trim()).split(":");
            String ip = hostTokens[0];

            if (hostTokens.length >= 1 && hostTokens.length <= 2) {
                if (hostTokens.length == 2 && !NetUtils.isValidPort(hostTokens[1])) {
                    return false;
                }
                if (ip.equalsIgnoreCase("localhost")) {
                    continue;
                }
                if (!NetUtils.isValidIp4(ip)) {
                    return false;
                }
            } else
            {
                return false;
            }
        }

        return true;
    }

    void parseMessage(String logMessage) {
        final StringTokenizer messageSplitter = new StringTokenizer(logMessage, _pairDelimiter);
        while (messageSplitter.hasMoreTokens()) {
            final String pairToken = messageSplitter.nextToken();
            final StringTokenizer pairSplitter = new StringTokenizer(pairToken, _keyValueDelimiter);
            String keyToken;
            String valueToken;

            if (pairSplitter.hasMoreTokens()) {
                keyToken = pairSplitter.nextToken().trim();
            } else {
                break;
            }

            if (pairSplitter.hasMoreTokens()) {
                valueToken = pairSplitter.nextToken().trim();
            } else {
                break;
            }

            if (keyToken.equalsIgnoreCase("alertType") && !valueToken.equalsIgnoreCase("null")) {
                alertType = Short.parseShort(valueToken);
            } else if (keyToken.equalsIgnoreCase("dataCenterId") && !valueToken.equalsIgnoreCase("null")) {
                dataCenterId = Long.parseLong(valueToken);
            } else if (keyToken.equalsIgnoreCase("podId") && !valueToken.equalsIgnoreCase("null")) {
                podId = Long.parseLong(valueToken);
            } else if (keyToken.equalsIgnoreCase("clusterId") && !valueToken.equalsIgnoreCase("null")) {
                clusterId = Long.parseLong(valueToken);
            } else if (keyToken.equalsIgnoreCase("message") && !valueToken.equalsIgnoreCase("null")) {
                sysMessage = getSyslogMessage(logMessage);
            }
        }
    }

    String createSyslogMessage() {
        StringBuilder message = new StringBuilder();
        message.append(severityOfAlert(alertType)).append(MESSAGE_DELIMITER_STRING);
        InetAddress ip;
        try {
            ip = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            ip = null;
        }

        if (ip != null) {
            message.append(ip.getHostName()).append(MESSAGE_DELIMITER_STRING);
        } else {
            message.append("unknown" + MESSAGE_DELIMITER_STRING);
        }

        if (alertType >= 0) {
            message.append("alertType").append(_keyValueDelimiter).append(" ").append(alertsMap.containsKey(alertType) ? alertsMap.get(alertType) : "unknown")
                    .append(MESSAGE_DELIMITER_STRING);
            if (dataCenterId != 0) {
                message.append("dataCenterId").append(_keyValueDelimiter).append(" ").append(dataCenterId).append(MESSAGE_DELIMITER_STRING);
            }

            if (podId != 0) {
                message.append("podId").append(_keyValueDelimiter).append(" ").append(podId).append(MESSAGE_DELIMITER_STRING);
            }

            if (clusterId != 0) {
                message.append("clusterId").append(_keyValueDelimiter).append(" ").append(clusterId).append(MESSAGE_DELIMITER_STRING);
            }

            if (sysMessage != null) {
                message.append("message").append(_keyValueDelimiter).append(" ").append(sysMessage);
            } else {
                errorHandler.error("What is the use of alert without message ");
            }
        } else {
            errorHandler.error("Invalid alert Type ");
        }

        return message.toString();
    }

    private String getSyslogMessage(String message) {
        int lastIndexOfKeyValueDelimiter = message.lastIndexOf(_keyValueDelimiter);
        int lastIndexOfMessageInString = message.lastIndexOf("message");

        if (lastIndexOfKeyValueDelimiter - lastIndexOfMessageInString <= LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER) {
            return message.substring(lastIndexOfKeyValueDelimiter + _keyValueDelimiter.length()).trim();
        } else if (lastIndexOfMessageInString < lastIndexOfKeyValueDelimiter) {
            return message.substring(lastIndexOfMessageInString + _keyValueDelimiter.length() + LENGTH_OF_STRING_MESSAGE).trim();
        }

        return message.substring(message.lastIndexOf("message" + _keyValueDelimiter) + LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER).trim();
    }

    private void reset() {
        _syslogAppenders.clear();
    }

    public void setFacility(String facility) {
        if (facility == null) {
            return;
        }

        _facility = facility;
        if (_syslogAppenders != null && !_syslogAppenders.isEmpty()) {
            for (SyslogAppender syslogAppender : _syslogAppenders) {
                syslogAppender.setFacility(facility);
            }
        }
    }

    private String severityOfAlert(int alertType) {
        if (isCritical(alertType)) {
            return "CRITICAL";
        } else {
            return "WARN";
        }
    }

    private boolean isCritical(int alertType) {
        for (int type : criticalAlerts) {
            if (type == alertType) {
                return true;
            }
        }
        return false;
    }

    public String getFacility() {
        return _facility;
    }

    public String getSyslogHosts() {
        return _syslogHosts;
    }

    public void setSyslogHosts(String syslogHosts) {
        _syslogHosts = syslogHosts;
        setSyslogAppenders();
    }

    public String getDelimiter() {
        return _delimiter;
    }

    public void setDelimiter(String delimiter) {
        _delimiter = delimiter;
    }

    public String getPairDelimiter() {
        return _pairDelimiter;
    }

    public void setPairDelimiter(String pairDelimiter) {
        _pairDelimiter = pairDelimiter;
    }

    public String getKeyValueDelimiter() {
        return _keyValueDelimiter;
    }

    public void setKeyValueDelimiter(String keyValueDelimiter) {
        _keyValueDelimiter = keyValueDelimiter;
    }
}
