/*
 * 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.mastership.MastershipService;

import org.slf4j.Logger;

import java.io.IOException;
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 (IOException 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();
    }

}
