/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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.provider.snmp.alarm.impl;

import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.I_Device;
import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0._OidRegistry;
import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.btisystems.btiproducts.bti7000.objects.conditions.ActAlarmTable;
import com.btisystems.mibbler.mibs.bti7000.interfaces.btisystems.btiproducts.bti7000.objects.conditions.IActAlarmTable;
import com.btisystems.pronx.ems.core.model.ClassRegistry;
import com.btisystems.pronx.ems.core.model.IClassRegistry;
import com.btisystems.pronx.ems.core.model.NetworkDevice;
import com.btisystems.pronx.ems.core.snmp.ISnmpSession;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.lang.StringUtils;
import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId;
import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
import org.onosproject.net.DeviceId;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;

/**
 * BTI 7000 specific implementation to provide a list of current alarms.
 * @deprecated 1.5.0 Falcon, not compliant with ONOS SB and driver architecture.
 */
@Deprecated
public class Bti7000SnmpAlarmProvider implements SnmpDeviceAlarmProvider {
    private final Logger log = getLogger(getClass());
    protected static final IClassRegistry CLASS_REGISTRY = new ClassRegistry(_OidRegistry.oidRegistry, I_Device.class);

    static final int ALARM_SEVERITY_MINOR = 2;
    static final int ALARM_SEVERITY_MAJOR = 3;
    static final int ALARM_SEVERITY_CRITICAL = 4;

    @Override
    public Collection<Alarm> getAlarms(ISnmpSession session, DeviceId deviceID) {
        log.info("Getting alarms for BTI 7000 device at {}", deviceID);
        Set<Alarm> alarms = new HashSet<>();
        NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY,
                session.getAddress().getHostAddress());

        try {
            session.walkDevice(networkDevice, Arrays.asList(
                    new OID[]{CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)}));

            IActAlarmTable deviceAlarms = (IActAlarmTable) networkDevice.getRootObject()
                .getEntity(CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class));
        if ((deviceAlarms != null) && (deviceAlarms.getActAlarmEntry() != null)
                && (!deviceAlarms.getActAlarmEntry().isEmpty())) {

            deviceAlarms.getActAlarmEntry().values().stream().forEach((alarm) -> {
                DefaultAlarm.Builder alarmBuilder = new DefaultAlarm.Builder(
                        deviceID, alarm.getActAlarmDescription(),
                        mapAlarmSeverity(alarm.getActAlarmSeverity()),
                        getLocalDateAndTime(alarm.getActAlarmDateAndTime(), null, null).getTime())
                        .forSource(AlarmEntityId.alarmEntityId("other:" + alarm.getActAlarmInstanceIdx()));
                alarms.add(alarmBuilder.build());
            });

        }
        log.info("Conditions retrieved: {}", deviceAlarms);

        } catch (IOException ex) {
            log.error("Error reading alarms for device {}.", deviceID, ex);
        }

        return alarms;
    }

    private Alarm.SeverityLevel mapAlarmSeverity(int intAlarmSeverity) {
        Alarm.SeverityLevel mappedSeverity;
        switch (intAlarmSeverity) {
            case ALARM_SEVERITY_MINOR:
                mappedSeverity = Alarm.SeverityLevel.MINOR;
                break;
            case ALARM_SEVERITY_MAJOR:
                mappedSeverity = Alarm.SeverityLevel.MAJOR;
                break;
            case ALARM_SEVERITY_CRITICAL:
                mappedSeverity = Alarm.SeverityLevel.CRITICAL;
                break;
            default:
                mappedSeverity = Alarm.SeverityLevel.MINOR;
                log.warn("Unexpected alarm severity: {}", intAlarmSeverity);
        }
        return mappedSeverity;
    }
    /**
     * Converts an SNMP string representation into a {@link Date} object,
     * and applies time zone conversion to provide the time on the local machine, ie PSM server.
     *
     * @param actAlarmDateAndTime MIB-II DateAndTime formatted. May optionally contain
     * a timezone offset in 3 extra bytes
     * @param sysInfoTimeZone Must be supplied if actAlarmDateAndTime is just local time (with no timezone)
     * @param swVersion Must be supplied if actAlarmDateAndTime is just local time (with no timezone)
     * @return adjusted {@link Date} or a simple conversion if other fields are null.
     */
    public static Date getLocalDateAndTime(String actAlarmDateAndTime, String sysInfoTimeZone,
            String swVersion) {
        if (StringUtils.isBlank(actAlarmDateAndTime)) {
            return null;
        }

        GregorianCalendar decodedDateAndTimeCal = btiMakeCalendar(OctetString.fromHexString(actAlarmDateAndTime));
        if ((sysInfoTimeZone == null) || (swVersion == null)) {
            return decodedDateAndTimeCal.getTime();
        }

        TimeZone javaTimeZone = getTimeZone();
        decodedDateAndTimeCal.setTimeZone(javaTimeZone);

        GregorianCalendar localTime = new GregorianCalendar();
        localTime.setTimeInMillis(decodedDateAndTimeCal.getTimeInMillis());

        return localTime.getTime();
    }

    /**
     * This method is similar to SNMP4J approach with some fixes for the 11-bytes version (ie the one with timezone
     * offset).
     *
     * For original makeCalendar refer @see http://www.snmp4j.org/agent/doc/org/snmp4j/agent/mo/snmp/DateAndTime.html
     *
     * Creates a <code>GregorianCalendar</code> from a properly formatted SNMP4J DateAndTime <code>OctetString</code>.
     *
     * @param dateAndTimeValue an OctetString conforming to the DateAndTime TC.
     * @return the corresponding <code>GregorianCalendar</code> instance.
     *
     */
    public static GregorianCalendar btiMakeCalendar(OctetString dateAndTimeValue) {
        int year = (dateAndTimeValue.get(0) & 0xFF) * 256
                + (dateAndTimeValue.get(1) & 0xFF);
        int month = (dateAndTimeValue.get(2) & 0xFF);
        int date = (dateAndTimeValue.get(3) & 0xFF);
        int hour = (dateAndTimeValue.get(4) & 0xFF);
        int minute = (dateAndTimeValue.get(5) & 0xFF);
        int second = (dateAndTimeValue.get(6) & 0xFF);
        int deci = (dateAndTimeValue.get(7) & 0xFF);
        GregorianCalendar gc =
                new GregorianCalendar(year, month - 1, date, hour, minute, second);
        gc.set(Calendar.MILLISECOND, deci * 100);

        if (dateAndTimeValue.length() == 11) {
            char directionOfOffset = (char) dateAndTimeValue.get(8);
            int hoursOffset = directionOfOffset == '+'
                    ? dateAndTimeValue.get(9) : -dateAndTimeValue.get(9);
            org.joda.time.DateTimeZone offset =
                    org.joda.time.DateTimeZone.forOffsetHoursMinutes(hoursOffset, dateAndTimeValue.get(10));
            org.joda.time.DateTime dt =
                    new org.joda.time.DateTime(year, month, date, hour, minute, second, offset);
            return dt.toGregorianCalendar();
        }
        return gc;
    }

    private static TimeZone getTimeZone() {
        return Calendar.getInstance().getTimeZone();
    }
}
