/*
 * Copyright 2016 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.oplink;

import com.google.common.collect.Range;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.onosproject.driver.extensions.OplinkAttenuation;
import org.onosproject.net.Device;
import org.onosproject.net.Direction;
import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.PowerConfig;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficTreatment;
import org.slf4j.Logger;

import java.util.Optional;

import static org.onosproject.drivers.oplink.OplinkOpticalUtility.POWER_MULTIPLIER;
import static org.onosproject.drivers.oplink.OplinkOpticalUtility.RANGE_ATT;
import static org.onosproject.drivers.oplink.OplinkOpticalUtility.RANGE_GENERAL;
import static org.onosproject.drivers.oplink.OplinkNetconfUtility.*;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Get current or target port/channel power from an Oplink optical netconf device.
 * Set target port power or channel attenuation to an optical netconf device.
 */
public class OplinkOpticalPowerConfig<T> extends AbstractHandlerBehaviour
        implements PowerConfig<T> {

    // key
    public static final String KEY_CHNUM = "wavelength-number";
    public static final String KEY_CHPWR = "wavelength-power";
    public static final String KEY_CHSTATS = "wavelength-stats";
    public static final String KEY_OCMSTATS = "ocm-stats";
    public static final String KEY_PORTDIRECT_RX = "rx";
    public static final String KEY_PORTDIRECT_TX = "tx";
    public static final String KEY_PORTTARPWR = "port-target-power";
    public static final String KEY_PORTCURPWR = "port-current-power";
    public static final String KEY_PORTPROPERTY = "port-property";
    public static final String KEY_PORTPWRCAPMINRX = "port-power-capability-min-rx";
    public static final String KEY_PORTPWRCAPMAXRX = "port-power-capability-max-rx";
    public static final String KEY_PORTPWRCAPMINTX = "port-power-capability-min-tx";
    public static final String KEY_PORTPWRCAPMAXTX = "port-power-capability-max-tx";
    public static final String KEY_PORTS_PORT = String.format("%s.%s", KEY_DATA_PORTS, KEY_PORT);
    public static final String KEY_PORTS_PORT_PROPERTY = String.format("%s.%s", KEY_PORTS_PORT, KEY_PORTPROPERTY);
    public static final String KEY_OCMS = "ocms";
    // log
    private static final Logger log = getLogger(OplinkOpticalPowerConfig.class);

    @Override
    public Optional<Double> getTargetPower(PortNumber port, T component) {
        Long power = acquireTargetPower(port, component);
        if (power == null) {
            return Optional.empty();
        }
        return Optional.of(power.doubleValue());
    }

    @Override
    public void setTargetPower(PortNumber port, T component, double power) {
        if (component instanceof OchSignal) {
            setChannelTargetPower(port, (OchSignal) component, (long) power);
        } else {
            setPortTargetPower(port, (long) power);
        }
    }

    @Override
    public Optional<Double> currentPower(PortNumber port, T component) {
        Long power = acquireCurrentPower(port, component);
        if (power == null) {
            return Optional.empty();
        }
        return Optional.of(power.doubleValue());
    }

    @Override
    public Optional<Range<Double>> getTargetPowerRange(PortNumber port, T component) {
        Range<Long> power = getTxPowerRange(port, component);
        if (power == null) {
            return Optional.empty();
        }
        return Optional.of(Range.closed((double) power.lowerEndpoint(), (double) power.upperEndpoint()));
    }

    @Override
    public Optional<Range<Double>> getInputPowerRange(PortNumber port, T component) {
        Range<Long> power = getRxPowerRange(port, component);
        if (power == null) {
            return Optional.empty();
        }
        return Optional.of(Range.closed((double) power.lowerEndpoint(), (double) power.upperEndpoint()));
    }

    private String getPortPowerFilter(PortNumber port, String selection) {
        return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
                .append(xmlOpen(KEY_PORTS))
                .append(xml(KEY_PORTID, Double.toString(port.toLong())))
                .append(xmlOpen(KEY_PORT))
                .append(xmlEmpty(selection))
                .append(xmlClose(KEY_PORT))
                .append(xmlClose(KEY_PORTS))
                .append(xmlClose(KEY_OPENOPTICALDEV))
                .toString();
    }

    private String getChannelPowerFilter(PortNumber port, OchSignal channel) {
        return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
                .append(xmlOpen(KEY_OCMS))
                .append(xml(KEY_PORTID, Double.toString(port.toLong())))
                .append(xmlOpen(KEY_OCMSTATS))
                .append(xml(KEY_CHNUM, Integer.toString(channel.spacingMultiplier())))
                .append(xmlEmpty(KEY_CHSTATS))
                .append(xmlClose(KEY_OCMSTATS))
                .append(xmlClose(KEY_OCMS))
                .append(xmlClose(KEY_OPENOPTICALDEV))
                .toString();
    }

    private String getChannelAttenuationFilter(PortNumber port, OchSignal channel) {
        return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
                .append(xmlOpen(KEY_CONNS))
                .append(xml(KEY_CONNID, Integer.toString(channel.spacingMultiplier())))
                .append(xmlEmpty(KEY_CHATT))
                .append(xmlClose(KEY_CONNS))
                .append(xmlClose(KEY_OPENOPTICALDEV))
                .toString();
    }

    private String getPowerRangeFilter(PortNumber port, String direction) {
        return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
                .append(xmlOpen(KEY_PORTS))
                .append(xml(KEY_PORTID, Double.toString(port.toLong())))
                .append(xmlOpen(KEY_PORT))
                .append(xml(KEY_PORTDIRECT, direction))
                .append(xmlEmpty(KEY_PORTPROPERTY))
                .append(xmlClose(KEY_PORT))
                .append(xmlClose(KEY_PORTS))
                .append(xmlClose(KEY_OPENOPTICALDEV))
                .toString();
    }

    private Long acquireTargetPower(PortNumber port, T component) {
        if (component instanceof OchSignal) {
            return acquireChannelAttenuation(port, (OchSignal) component);
        }
        log.debug("Get port{} target power...", port);
        return acquirePortPower(port, KEY_PORTTARPWR);
    }

    private Long acquireCurrentPower(PortNumber port, T component) {
        if (component instanceof OchSignal) {
            return acquireChannelPower(port, (OchSignal) component);
        }
        log.debug("Get port{} current power...", port);
        return acquirePortPower(port, KEY_PORTCURPWR);
    }

    private Long acquirePortPower(PortNumber port, String selection) {
        String reply = netconfGet(handler(), getPortPowerFilter(port, selection));
        HierarchicalConfiguration info = configAt(reply, KEY_PORTS_PORT);
        if (info == null) {
            return null;
        }
        return (long) (info.getDouble(selection) * POWER_MULTIPLIER);
    }

    private Long acquireChannelAttenuation(PortNumber port, OchSignal channel) {
        log.debug("Get port{} channel{} attenuation...", port, channel.channelSpacing());
        String reply = netconfGet(handler(), getChannelAttenuationFilter(port, channel));
        HierarchicalConfiguration info = configAt(reply, KEY_CONNS);
        if (info == null) {
            return null;
        }
        return (long) (info.getDouble(KEY_CHATT) * POWER_MULTIPLIER);
    }

    private Long acquireChannelPower(PortNumber port, OchSignal channel) {
        log.debug("Get port{} channel{} power...", port, channel.channelSpacing());
        String reply = netconfGet(handler(), getChannelPowerFilter(port, channel));
        HierarchicalConfiguration info = configAt(reply, KEY_DATA_CONNS);
        if (info == null) {
            return null;
        }
        return (long) (info.getDouble(KEY_CHPWR) * POWER_MULTIPLIER);
    }

    private boolean setPortTargetPower(PortNumber port, long power) {
        log.debug("Set port{} target power...", port);
        String cfg = new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
                .append(xmlOpen(KEY_PORTS))
                .append(xml(KEY_PORTID, Double.toString(port.toLong())))
                .append(xmlOpen(KEY_PORT))
                .append(xml(KEY_PORTTARPWR, Double.toString(power)))
                .append(xmlClose(KEY_PORT))
                .append(xmlClose(KEY_PORTS))
                .append(xmlClose(KEY_OPENOPTICALDEV))
                .toString();
        return netconfEditConfig(handler(), CFG_MODE_MERGE, cfg);
    }

    private boolean setChannelTargetPower(PortNumber port, OchSignal channel, long power) {
        log.debug("Set port{} channel{} attenuation.", port, channel.channelSpacing());
        FlowRuleService service = handler().get(FlowRuleService.class);
        Iterable<FlowEntry> entries = service.getFlowEntries(data().deviceId());
        for (FlowEntry entry : entries) {
            OplinkCrossConnect crossConnect = OplinkOpticalUtility.fromFlowRule(this, entry);
            // The channel port might be input port or output port.
            if ((port.equals(crossConnect.getInPort()) || port.equals(crossConnect.getOutPort())) &&
                    channel.spacingMultiplier() == crossConnect.getChannel()) {
                log.debug("Flow is found, modify the flow with attenuation.");
                // Modify attenuation in treatment
                TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                        .setOutput(crossConnect.getOutPort())
                        .extension(new OplinkAttenuation((int) power), data().deviceId())
                        .build();
                // Apply the new flow rule
                service.applyFlowRules(DefaultFlowRule.builder()
                        .forDevice(data().deviceId())
                        .makePermanent()
                        .withSelector(entry.selector())
                        .withTreatment(treatment)
                        .withPriority(entry.priority())
                        .withCookie(entry.id().value())
                        .build());
                return true;
            }
        }
        return false;
    }

    private Range<Long> getPowerRange(PortNumber port, String directionKey, String minKey, String maxKey) {
        // TODO
        // Optical protection switch does not support power range configuration, it'll reply error.
        // To prevent replying error log flooding from netconf session when polling all ports information,
        // use general power range of [-60, 60] instead.
        if (handler().get(DeviceService.class).getDevice(data().deviceId()).type()
                == Device.Type.FIBER_SWITCH) {
            return RANGE_GENERAL;
        }
        String reply = netconfGet(handler(), getPowerRangeFilter(port, directionKey));
        HierarchicalConfiguration info = configAt(reply, KEY_PORTS_PORT_PROPERTY);
        if (info == null) {
            return null;
        }
        long minPower = (long) (info.getDouble(minKey) * POWER_MULTIPLIER);
        long maxPower = (long) (info.getDouble(maxKey) * POWER_MULTIPLIER);
        return Range.closed(minPower, maxPower);
    }

    private Range<Long> getTxPowerRange(PortNumber port, T component) {
        if (component instanceof Direction) {
            log.debug("Get target port{} power range...", port);
            return getPowerRange(port, KEY_PORTDIRECT_TX, KEY_PORTPWRCAPMINTX, KEY_PORTPWRCAPMAXTX);
        } else {
            log.debug("Get channel attenuation range...");
            return RANGE_ATT;
        }
    }

    private Range<Long> getRxPowerRange(PortNumber port, T component) {
        log.debug("Get input port{} power range...", port);
        return getPowerRange(port, KEY_PORTDIRECT_RX, KEY_PORTPWRCAPMINRX, KEY_PORTPWRCAPMAXRX);
    }
}
