/*
 * 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.net.device.impl;

import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
import static org.onosproject.net.optical.device.OmsPortHelper.omsPortDescription;
import static org.slf4j.LoggerFactory.getLogger;
import static com.google.common.base.Preconditions.checkNotNull;

import org.onosproject.net.config.ConfigOperator;
import org.onosproject.net.config.basics.OpticalPortConfig;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.OtuPort;
import org.onosproject.net.OduCltPort;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.OchPortDescription;
import org.onosproject.net.device.OduCltPortDescription;
import org.onosproject.net.device.OmsPortDescription;
import org.onosproject.net.device.OtuPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.optical.OchPort;
import org.onosproject.net.optical.OmsPort;
import org.onosproject.net.optical.OpticalDevice;
import org.slf4j.Logger;

/**
 * Implementations of merge policies for various sources of optical port
 * configuration information. This includes applications, provides, and network
 * configurations.
 */
public final class OpticalPortOperator implements ConfigOperator {

    private static final Logger log = getLogger(OpticalPortOperator.class);

    private OpticalPortOperator() {
    }

    /**
     * Generates a PortDescription containing fields from a PortDescription and
     * an OpticalPortConfig.
     *
     * @param opc the port config entity from network config
     * @param descr a PortDescription
     * @return PortDescription based on both sources
     */
    public static PortDescription combine(OpticalPortConfig opc, PortDescription descr) {
        if (opc == null) {
            return descr;
        }

        PortNumber port = descr.portNumber();
        final String name = opc.name();
        final String numName = opc.numberName();
        // if the description is null, or the current description port name != config name,
        // create a new PortNumber.
        PortNumber newPort = null;
        if (port == null) {
            // try to get the portNumber from the numName.
            if (!numName.isEmpty()) {
                final long pn = Long.parseLong(numName);
                newPort = (!name.isEmpty()) ? PortNumber.portNumber(pn, name) : PortNumber.portNumber(pn);
            } else {
                // we don't have defining info (a port number value)
                throw new RuntimeException("Possible misconfig, bailing on handling for: \n\t" + descr);
            }
        } else if ((!name.isEmpty()) && !name.equals(port.name())) {
            final long pn = (numName.isEmpty()) ? port.toLong() : Long.parseLong(numName);
            newPort = PortNumber.portNumber(pn, name);
        }

        // Port type won't change unless we're overwriting a port completely.
        // Watch out for overwrites to avoid class cast craziness.
        boolean noOwrite = opc.type() == descr.type();

        SparseAnnotations sa = combine(opc, descr.annotations());
        if (noOwrite) {
            return updateDescription((newPort == null) ? port : newPort, sa, descr);
        } else {
            // TODO: must reconstruct a different type of PortDescription.
            log.info("Type rewrite from {} to {} required", descr.type(), opc.type());
        }
        return descr;
    }

    // updates a port description whose port type has not changed.
    private static PortDescription updateDescription(
            PortNumber port, SparseAnnotations sa, PortDescription descr) {
        switch (descr.type()) {
            case OMS:
                if (descr instanceof OmsPortDescription) {
                    // TODO This block can go away once deprecation is complete.
                    OmsPortDescription oms = (OmsPortDescription) descr;
                    return omsPortDescription(port, oms.isEnabled(), oms.minFrequency(),
                                                  oms.maxFrequency(), oms.grid(), sa);
                }
                return descr;
            case OCH:
                // We might need to update lambda below with STATIC_LAMBDA.
                if (descr instanceof OchPortDescription) {
                    // TODO This block can go away once deprecation is complete.
                    OchPortDescription och = (OchPortDescription) descr;
                    return ochPortDescription(port, och.isEnabled(), och.signalType(),
                            och.isTunable(), och.lambda(), sa);
                }
                return descr;
            case ODUCLT:
                OduCltPortDescription odu = (OduCltPortDescription) descr;
                return new OduCltPortDescription(port, odu.isEnabled(), odu.signalType(), sa);
            case PACKET:
            case FIBER:
            case COPPER:
                // TODO: it should be safe to just return descr. confirm and fix
                return new DefaultPortDescription(port, descr.isEnabled(), descr.type(),
                        descr.portSpeed(), sa);
            case OTU:
                OtuPortDescription otu = (OtuPortDescription) descr;
                return new OtuPortDescription(port, otu.isEnabled(), otu.signalType(), sa);
            default:
                log.warn("Unsupported optical port type {} - can't update", descr.type());
                return descr;
        }
    }

    /**
     * Generates an annotation from an existing annotation and OptcalPortConfig.
     *
     * @param opc the port config entity from network config
     * @param an the annotation
     * @return annotation combining both sources
     */
    public static SparseAnnotations combine(OpticalPortConfig opc, SparseAnnotations an) {
        DefaultAnnotations.Builder b = DefaultAnnotations.builder();
        if (!opc.staticPort().isEmpty()) {
            b.set(AnnotationKeys.STATIC_PORT, opc.staticPort());
        }
        if (opc.staticLambda().isPresent()) {
            b.set(AnnotationKeys.STATIC_LAMBDA, String.valueOf(opc.staticLambda().get()));
        }
        // The following may not need to be carried.
        if (!opc.name().isEmpty()) {
            b.set(AnnotationKeys.PORT_NAME, opc.name());
        }
        return DefaultAnnotations.union(an, b.build());
    }

    /**
     * Returns a description built from an existing port.
     *
     * @param port the device port
     * @return a PortDescription based on the port
     */
    public static PortDescription descriptionOf(Port port) {
        checkNotNull(port, "Must supply non-null Port");
        final boolean isUp = port.isEnabled();
        return descriptionOfPort(port, isUp);
    }

    /**
     * Returns a description built from an existing port and reported status.
     *
     * @param port port
     * @param isEnabled true if enabled
     * @return a PortDescription based on the port
     */
    static PortDescription descriptionOf(Port port, boolean isEnabled) {
        checkNotNull(port, "Must supply non-null Port");
        final boolean isup = isEnabled;
        return descriptionOfPort(port, isup);
    }

    private static PortDescription descriptionOfPort(Port port, final boolean isup) {
        final PortNumber ptn = port.number();
        final SparseAnnotations an = (SparseAnnotations) port.annotations();
        switch (port.type()) {
            case OMS:
                if (port instanceof org.onosproject.net.OmsPort) {
                    // remove if-block once deprecation is complete
                    org.onosproject.net.OmsPort oms = (org.onosproject.net.OmsPort) port;
                    return omsPortDescription(ptn, isup, oms.minFrequency(),
                                              oms.maxFrequency(), oms.grid(), an);
                }
                if (port.element().is(OpticalDevice.class)) {
                    OpticalDevice optDevice = port.element().as(OpticalDevice.class);
                    if (optDevice.portIs(port, OmsPort.class)) {
                        OmsPort oms = optDevice.portAs(port, OmsPort.class).get();
                        return omsPortDescription(ptn, isup, oms.minFrequency(),
                                                  oms.maxFrequency(), oms.grid(), an);
                    }
                }
                return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);
            case OCH:
                if (port instanceof org.onosproject.net.OchPort) {
                    // remove if-block once old OchPort deprecation is complete
                    org.onosproject.net.OchPort och = (org.onosproject.net.OchPort) port;
                    return ochPortDescription(ptn, isup, och.signalType(),
                                              och.isTunable(), och.lambda(), an);
                }
                if (port.element().is(OpticalDevice.class)) {
                    OpticalDevice optDevice = port.element().as(OpticalDevice.class);
                    if (optDevice.portIs(port, OchPort.class)) {
                        OchPort och = optDevice.portAs(port, OchPort.class).get();
                        return ochPortDescription(ptn, isup, och.signalType(),
                                                  och.isTunable(), och.lambda(), an);
                    }
                }
                return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);

            case ODUCLT:
                OduCltPort odu = (OduCltPort) port;
                return new OduCltPortDescription(ptn, isup, odu.signalType(), an);
            case OTU:
                OtuPort otu = (OtuPort) port;
                return new OtuPortDescription(ptn, isup, otu.signalType(), an);
            default:
                return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);
        }
    }
}
