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

import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.util.Optional;

import org.onosproject.net.Annotations;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultAnnotations.Builder;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OduSignalType;
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.PortDescription;
import org.onosproject.net.optical.OchPort;
import org.onosproject.net.optical.impl.DefaultOchPort;
import org.onosproject.net.optical.json.OchSignalCodec;
import org.slf4j.Logger;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableSet;

/**
 * OCh port related helpers.
 */
@Beta
public final class OchPortHelper {

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

    private static final ObjectMapper MAPPER = new ObjectMapper();

    // Annotation keys
    private static final String SIGNAL_TYPE = "signalType";
    private static final String TUNABLE = "tunable";
    private static final String LAMBDA = "lambda";

    /**
     * Creates OCh port DefaultPortDescription based on the supplied information.
     *
     * @param number      port number
     * @param isEnabled   port enabled state
     * @param signalType  ODU signal type
     * @param isTunable   tunable wavelength capability
     * @param lambda      OCh signal
     * @return OCh port DefaultPortDescription with OCh annotations
     */
    public static PortDescription ochPortDescription(PortNumber number,
                                                     boolean isEnabled,
                                                     OduSignalType signalType,
                                                     boolean isTunable,
                                                     OchSignal lambda) {
        return ochPortDescription(number, isEnabled, signalType, isTunable, lambda, DefaultAnnotations.EMPTY);
    }

    /**
     * Creates OCh port DefaultPortDescription based on the supplied information.
     *
     * @param number      port number
     * @param isEnabled   port enabled state
     * @param signalType  ODU signal type
     * @param isTunable   tunable wavelength capability
     * @param lambda      OCh signal
     * @param annotationsIn key/value annotations map
     * @return OCh port DefaultPortDescription with OCh annotations
     */
    public static PortDescription ochPortDescription(PortNumber number,
                                                     boolean isEnabled,
                                                     OduSignalType signalType,
                                                     boolean isTunable,
                                                     OchSignal lambda,
                                                     SparseAnnotations annotationsIn) {

        Builder builder = DefaultAnnotations.builder();
        builder.putAll(annotationsIn);

        builder.set(TUNABLE, String.valueOf(isTunable));
        builder.set(LAMBDA, OchSignalCodec.encode(lambda).toString());
        builder.set(SIGNAL_TYPE, signalType.toString());

        DefaultAnnotations annotations = builder.build();
        long portSpeed = signalType.bitRate();
        return DefaultPortDescription.builder().withPortNumber(number).isEnabled(isEnabled)
                .type(Port.Type.OCH).portSpeed(portSpeed).annotations(annotations)
                .build();
    }

    /**
     * Creates OCh port DefaultPortDescription based on the supplied information.
     *
     * @param base        PortDescription to get basic information from
     * @param signalType  ODU signal type
     * @param isTunable   tunable wavelength capability
     * @param lambda      OCh signal
     * @param annotations key/value annotations map
     * @return OCh port DefaultPortDescription with OCh annotations
     */
    public static PortDescription ochPortDescription(PortDescription base,
                                                     OduSignalType signalType,
                                                     boolean isTunable,
                                                     OchSignal lambda,
                                                     SparseAnnotations annotations) {
        return ochPortDescription(base.portNumber(), base.isEnabled(), signalType, isTunable, lambda, annotations);
    }


    public static Optional<OchPort> asOchPort(Port port) {
        if (port instanceof OchPort) {
            return Optional.of((OchPort) port);
        }

        try {
            Annotations an = port.annotations();

            OduSignalType signalType = Enum.valueOf(OduSignalType.class,
                                                    an.value(SIGNAL_TYPE));

            boolean isTunable = Boolean.valueOf(an.value(TUNABLE));

            ObjectNode obj = (ObjectNode) MAPPER.readTree(an.value(LAMBDA));
            OchSignal lambda = OchSignalCodec.decode(obj);

            // Note: OCh specific annotations is not filtered-out here.
            //       DefaultOchPort should filter them, if necessary.
            return Optional.of(new DefaultOchPort(port, signalType, isTunable, lambda));

            // TODO: it'll be better to verify each inputs properly
            // instead of catching all these Exceptions.
        } catch (IOException | NullPointerException
                | IllegalArgumentException | ClassCastException e) {

            log.warn("{} was not well-formed OCh port.", port, e);
            return Optional.empty();
        }
    }

    /**
     * Returns {@link Annotations} not used by the port type projection.
     *
     * @param input {@link Annotations}
     * @return filtered view of given {@link Annotations}
     */
    public static Annotations stripHandledAnnotations(Annotations input) {
        return new FilteredAnnotation(input, ImmutableSet.of(SIGNAL_TYPE, TUNABLE, LAMBDA));
    }

    // not meant to be instantiated
    private OchPortHelper() {}
}
