/*
 * 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.alarm.Alarm;
import org.onosproject.alarm.AlarmConsumer;
import org.onosproject.alarm.AlarmEntityId;
import org.onosproject.alarm.AlarmId;
import org.onosproject.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.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 exist: 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(
                            AlarmId.alarmId(ncDeviceId, Long.toString(timeRaised)),
                            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 exist", 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 exist", DATE, TIME);
                }
            }
        }
        // Use the system's time instead.
        return System.currentTimeMillis();
    }

}
