/*
 * Copyright 2016-present Open Networking Foundation
 *
 * Licensed 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.onosproject.drivers.fujitsu;

import com.google.common.collect.ImmutableList;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.onosproject.drivers.utilities.XmlConfigParser;
import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId;
import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
import org.onosproject.net.DeviceId;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.mastership.MastershipService;

import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.TimeZone;

import java.nio.charset.StandardCharsets;
import java.io.ByteArrayInputStream;

import static org.onosproject.incubator.net.faultmanagement.alarm.Alarm.SeverityLevel;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.drivers.fujitsu.FujitsuVoltXmlUtility.*;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Fujitsu vOLT specific implementation to provide a list of current alarms.
 */
public class FujitsuVoltAlarmConsumer extends AbstractHandlerBehaviour implements AlarmConsumer {
    private final Logger log = getLogger(getClass());
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static final TimeZone ZONE =  TimeZone.getTimeZone("UTC");

    private static final String VOLT_ALERTS = "volt-alerts";
    private static final String OLT_ACTIVE_ALERTS = "olt-active-alerts";
    private static final String ALERT_INFO = "alert-info";
    private static final String ALERT_SEQNUM = "alert-seqnum";
    private static final String ALERT_TYPE = "alert-type";
    private static final String ALERT_TIME = "alert-time";
    private static final String ALERT_CLEAR = "alert-clear";
    private static final String RESOURCE_ID = "resource-id";
    private static final String SEVERITY = "severity";
    private static final String IP_ADDRESS = "ip-address";
    private static final String DATE = "date";
    private static final String TIME = "time";
    private static final String OLT_ACTIVE_ALERTS_KEY =
            "data." + VOLT_NE + ".volt-alerts.olt-active-alerts";
    private static final String SLASH = "/";
    private DeviceId ncDeviceId;

    private enum AlertResourceType {
        UNKNOWN,
        PONLINK,
        ONU,
        SYSTEM
    }

    private enum AlertSeverity {
        INFO("info", SeverityLevel.WARNING),
        MINOR("minor", SeverityLevel.MINOR),
        MAJOR("major", SeverityLevel.MAJOR),
        CRITICAL("critical", SeverityLevel.CRITICAL);

        private String text;
        private SeverityLevel level;

        AlertSeverity(String text, SeverityLevel level) {
            this.text = text;
            this.level = level;
        }

        public static SeverityLevel convertToAlarmSeverityLevel(String text) {
            for (AlertSeverity severity : AlertSeverity.values()) {
                if (text.equalsIgnoreCase(severity.text)) {
                    return severity.level;
                }
            }
            return SeverityLevel.INDETERMINATE;
        }
    }

    @Override
    public List<Alarm> consumeAlarms() {
        DriverHandler handler = handler();
        NetconfController controller = handler.get(NetconfController.class);
        MastershipService mastershipService = handler.get(MastershipService.class);
        ncDeviceId = handler.data().deviceId();
        checkNotNull(controller, "Netconf controller is null");

        if (!mastershipService.isLocalMaster(ncDeviceId)) {
            log.warn("Not master for {} Use {} to execute command",
                     ncDeviceId,
                     mastershipService.getMasterFor(ncDeviceId));
            return null;
        }

        dateFormat.setTimeZone(ZONE);
        List<Alarm> alarms = new ArrayList<>();
        try {
            StringBuilder request = new StringBuilder();
            request.append(VOLT_NE_OPEN + VOLT_NE_NAMESPACE)
                .append(ANGLE_RIGHT + NEW_LINE)
                .append(buildStartTag(VOLT_ALERTS))
                .append(buildEmptyTag(OLT_ACTIVE_ALERTS))
                .append(buildEndTag(VOLT_ALERTS))
                .append(VOLT_NE_CLOSE);

            String reply = controller.getDevicesMap()
                               .get(ncDeviceId)
                               .getSession()
                               .get(request.toString(), null);
            if (reply != null) {
                alarms = parseVoltActiveAlerts(XmlConfigParser.
                    loadXml(new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
            }
        } catch (NetconfException e) {
            log.error("Error reading alarms for device {} exception {}", ncDeviceId, e);
        }

        return ImmutableList.copyOf(alarms);
    }

    /**
     * Parses XML string to get controller information.
     *
     * @param cfg a hierarchical configuration
     * @return a list of alarms
     */
    private List<Alarm> parseVoltActiveAlerts(HierarchicalConfiguration cfg) {
        List<Alarm> alarms = new ArrayList<>();
        List<HierarchicalConfiguration> fields =
                cfg.configurationsAt(OLT_ACTIVE_ALERTS_KEY);

        for (HierarchicalConfiguration sub : fields) {
            List<HierarchicalConfiguration> childFields =
                    sub.configurationsAt(ALERT_INFO);

            for (HierarchicalConfiguration child : childFields) {
                try {
                    int seqNum = Integer.parseInt(child.getString(ALERT_SEQNUM));
                    boolean cleared = Boolean.parseBoolean(child.getString(ALERT_CLEAR));
                    String alertType = child.getString(ALERT_TYPE);
                    String severity = child.getString(SEVERITY);

                    List<HierarchicalConfiguration> idFields =
                            child.configurationsAt(RESOURCE_ID);
                    if (idFields.isEmpty()) {
                        log.error("{} does not exsit: SQ={}, TYPE={}, SEV={}, CLEARED={}",
                                RESOURCE_ID, seqNum, alertType, severity, cleared);
                        continue;
                    }
                    String alarmSrc = formAlarmSource(idFields);
                    if (alarmSrc == null) {
                        log.error("Cannot build description: SQ={}, TYPE={}, SEV={}, CLEARED={}",
                                seqNum, alertType, severity, cleared);
                        continue;
                    }
                    long timeRaised = getTimeRaised(child);
                    log.debug("VOLT: ACTIVE ALERT: SQ={}, TYPE={}, SEV={}, CLEARED={}, TIME={}",
                            seqNum, alertType, severity, cleared, timeRaised);

                    SeverityLevel alarmLevel =
                            AlertSeverity.convertToAlarmSeverityLevel(severity);
                    if (alarmLevel.equals(SeverityLevel.INDETERMINATE)) {
                        log.warn("Unknown severity: {}", severity);
                    }
                    DefaultAlarm.Builder alarmBuilder = new DefaultAlarm.Builder(
                            ncDeviceId, alertType.toUpperCase(), alarmLevel, timeRaised)
                            .forSource(AlarmEntityId.alarmEntityId(alarmSrc));
                    alarms.add(alarmBuilder.build());
                } catch (NumberFormatException e) {
                    log.error("Non-number exception {}", e);
                } catch (Exception e) {
                    log.error("Exception {}", e);
                }
            }
        }
        return alarms;
    }

    /**
     * Builds alarm source with resource information.
     * @param idFields a hierarchical configuration
     * @return formed alarm description
     */
    private String formAlarmSource(List<HierarchicalConfiguration> idFields) {
        AlertResourceType resourceType = AlertResourceType.UNKNOWN;
        StringBuilder alarmSrc = new StringBuilder();
        String ipAddr = null;
        int pon = ZERO;
        int onu = ZERO;

        for (HierarchicalConfiguration id : idFields) {
            String value;
            try {
                value = id.getString(PONLINK_ID);
                if (value == null) {
                    resourceType = AlertResourceType.SYSTEM;
                    ipAddr = id.getString(IP_ADDRESS);
                } else {
                    pon = Integer.parseInt(value);
                    value = id.getString(ONU_ID);
                    if (value == null) {
                        resourceType = AlertResourceType.PONLINK;
                    } else {
                        resourceType = AlertResourceType.ONU;
                        onu = Integer.parseInt(value);
                    }
                }
            } catch (NumberFormatException e) {
                log.error("Non-number resource-id exception {}", e);
                return null;
            }
        }

        alarmSrc.append("other:");
        alarmSrc.append(resourceType.name()).append(SLASH);
        switch (resourceType) {
            case PONLINK:
                alarmSrc.append(pon);
                break;
            case ONU:
                alarmSrc.append(pon).append(HYPHEN).append(onu);
                break;
            case SYSTEM:
                if (ipAddr != null) {
                    alarmSrc.append(ipAddr);
                }
                break;
            default:
                break;
        }
        return alarmSrc.toString();
    }

    /**
     * Converts time and date information from device.
     * @param cfg a hierarchical configuration
     * @return converted time from device or system time
     */
    private long getTimeRaised(HierarchicalConfiguration cfg) {
        String strDate;
        String strTime;
        long timeRaised;

        List<HierarchicalConfiguration> timeFields =
                cfg.configurationsAt(ALERT_TIME);
        if (timeFields.isEmpty()) {
            log.debug("{} does not exsit", ALERT_TIME);
        } else {
            for (HierarchicalConfiguration child : timeFields) {
                strDate = child.getString(DATE);
                strTime = child.getString(TIME);
                if ((strDate != null) && (strTime != null)) {
                    try {
                        Date date = dateFormat.parse(strDate + SPACE + strTime);
                        timeRaised = date.getTime();
                        log.debug("{} {} converted to {}", strDate, strTime, timeRaised);
                        return timeRaised;
                    } catch (ParseException e) {
                        log.error("Cannot parse exception {} {} {}", strDate, strTime, e);
                    }
                } else {
                    log.error("{} or {} does not exsit", DATE, TIME);
                }
            }
        }
        // Use the system's time instead.
        return System.currentTimeMillis();
    }

}
