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

import static org.slf4j.LoggerFactory.getLogger;

import java.util.Optional;

import org.onosproject.net.Annotations;
import org.onosproject.net.CltSignalType;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.DefaultAnnotations.Builder;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.optical.OduCltPort;
import org.onosproject.net.optical.impl.DefaultOduCltPort;
import org.slf4j.Logger;

import com.google.common.annotations.Beta;

/**
 * ODU client port related helpers.
 */
@Beta
public final class OduCltPortHelper {

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

    // Annotation keys
    /**
     * {@link CltSignalType} as String.
     */
    private static final String SIGNAL_TYPE = "signalType";

    /**
     * Creates ODU client port description based on the supplied information.
     *
     * @param number        port number
     * @param isEnabled     port enabled state
     * @param signalType    ODU client signal type
     */
    public static PortDescription oduCltPortDescription(PortNumber number,
                                        boolean isEnabled,
                                        CltSignalType signalType) {
        return oduCltPortDescription(number, isEnabled, signalType, DefaultAnnotations.EMPTY);
    }

    /**
     * Creates ODU client port description based on the supplied information.
     *
     * @param number        port number
     * @param isEnabled     port enabled state
     * @param signalType    ODU client signal type
     * @param annotations   key/value annotations map
     */
    public static PortDescription oduCltPortDescription(PortNumber number,
                                                        boolean isEnabled,
                                                        CltSignalType signalType,
                                                        SparseAnnotations annotations) {
        Builder builder = DefaultAnnotations.builder();
        builder.putAll(annotations);

        builder.set(SIGNAL_TYPE, signalType.toString());

        long portSpeed = signalType.bitRate();
        return new DefaultPortDescription(number,
                                          isEnabled,
                                          Port.Type.ODUCLT,
                                          portSpeed,
                                          builder.build());
    }

    /**
     * Creates ODU client port description based on the supplied information.
     *
     * @param base          PortDescription to get basic information from
     * @param signalType    ODU client signal type
     * @param annotations   key/value annotations map
     */
    public static PortDescription oduCltPortDescription(PortDescription base,
                                                        CltSignalType signalType,
                                                        SparseAnnotations annotations) {
        return oduCltPortDescription(base.portNumber(), base.isEnabled(), signalType, annotations);
    }

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

        try {
            Annotations an = port.annotations();

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


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

        } catch (NullPointerException | IllegalArgumentException e) {

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

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