/*
 * 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.OduCltPortHelper.oduCltPortDescription;
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.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.OduCltPort;
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:
                if (descr instanceof OduCltPortDescription) {
                    // TODO This block can go away once deprecation is complete.
                    OduCltPortDescription odu = (OduCltPortDescription) descr;
                    return oduCltPortDescription(port, odu.isEnabled(), odu.signalType(), sa);
                }
                return descr;
            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:
                if (port instanceof org.onosproject.net.OduCltPort) {
                    // remove if-block once deprecation is complete
                    org.onosproject.net.OduCltPort odu = (org.onosproject.net.OduCltPort) port;
                    return oduCltPortDescription(ptn, isup, odu.signalType(), an);
                }
                if (port.element().is(OpticalDevice.class)) {
                    OpticalDevice optDevice = port.element().as(OpticalDevice.class);
                    if (optDevice.portIs(port, OduCltPort.class)) {
                        OduCltPort odu = (OduCltPort) port;
                        return oduCltPortDescription(ptn, isup, odu.signalType(), an);
                    }
                }
                return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), 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);
        }
    }
}
