/*
 * 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.incubator.rpc.grpc;

import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
import io.grpc.Channel;
import org.onosproject.grpc.net.link.LinkProviderServiceRpcGrpc;
import org.onosproject.grpc.net.link.LinkProviderServiceRpcGrpc.LinkProviderServiceRpcFutureStub;
import org.onosproject.grpc.net.link.LinkService.LinkDetectedMsg;
import org.onosproject.grpc.net.link.LinkService.LinkVanishedMsg;
import org.onosproject.grpc.net.link.LinkService.Void;
import org.onosproject.grpc.net.link.models.LinkEnumsProto.LinkTypeProto;
import org.onosproject.grpc.net.models.ConnectPointProtoOuterClass.ConnectPointProto;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link.Type;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.onosproject.incubator.protobuf.models.ProtobufUtils.asMap;

/**
 * Proxy object to handle LinkProviderService calls.
 *
 * RPC wise, this will initiate a RPC call on each method invocation.
 */
@Beta
class LinkProviderServiceClientProxy
    extends AbstractProviderService<LinkProvider>
    implements LinkProviderService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    private final Channel channel;

    /**
     * Constructs {@link LinkProviderServiceClientProxy}.
     *
     * @param provider {@link LinkProvider}. Only ProviderId scheme is used.
     * @param channel channel to use to call RPC
     */
    protected LinkProviderServiceClientProxy(LinkProvider provider, Channel channel) {
        super(provider);
        this.channel = channel;
    }

    @Override
    public void linkDetected(LinkDescription linkDescription) {
        checkValidity();

        LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
        ListenableFuture<Void> future = newStub.linkDetected(detectMsg(provider().id(), linkDescription));

        try {
            // There's no need to wait, but just checking server
            future.get(500, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("linkDetected({}) failed", linkDescription, e);
            invalidate();
            Thread.currentThread().interrupt();
        } catch (ExecutionException | TimeoutException e) {
            log.error("linkDetected({}) failed", linkDescription, e);
            invalidate();
        }
    }

    @Override
    public void linkVanished(LinkDescription linkDescription) {
        checkValidity();

        LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
        ListenableFuture<Void> future = newStub.linkVanished(vanishMsg(provider().id(), linkDescription));

        try {
            // There's no need to wait, but just checking server
            future.get(500, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("linkVanished({}) failed", linkDescription, e);
            invalidate();
            Thread.currentThread().interrupt();
        } catch (ExecutionException | TimeoutException e) {
            log.error("linkVanished({}) failed", linkDescription, e);
            invalidate();
        }
    }

    @Override
    public void linksVanished(ConnectPoint connectPoint) {
        checkValidity();

        LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
        ListenableFuture<Void> future = newStub.linkVanished(vanishMsg(provider().id(), connectPoint));

        try {
            // There's no need to wait, but just checking server
            future.get(500, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("linksVanished({}) failed", connectPoint, e);
            invalidate();
            Thread.currentThread().interrupt();
        } catch (ExecutionException | TimeoutException e) {
            log.error("linksVanished({}) failed", connectPoint, e);
            invalidate();
        }
    }

    @Override
    public void linksVanished(DeviceId deviceId) {
        checkValidity();

        LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
        ListenableFuture<Void> future = newStub.linkVanished(vanishMsg(provider().id(), deviceId));

        try {
            // There's no need to wait, but just checking server
            future.get(500, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("linksVanished({}) failed", deviceId, e);
            invalidate();
            Thread.currentThread().interrupt();
        } catch (ExecutionException | TimeoutException e) {
            log.error("linksVanished({}) failed", deviceId, e);
            invalidate();
        }
    }

    /**
     * Builds {@link LinkDetectedMsg}.
     *
     * @param id ProviderId
     * @param linkDescription {@link LinkDescription}
     * @return {@link LinkDetectedMsg}
     */
    private LinkDetectedMsg detectMsg(ProviderId id,
                                      LinkDescription linkDescription) {
        LinkDetectedMsg.Builder builder = LinkDetectedMsg.newBuilder();
        builder.setProviderId(id.scheme())
               .setLinkDescription(builder.getLinkDescriptionBuilder()
                                    .setSrc(translate(linkDescription.src()))
                                    .setDst(translate(linkDescription.dst()))
                                    .setType(translate(linkDescription.type()))
                                    .putAllAnnotations(asMap(linkDescription.annotations()))
                                    .build()
                                    );
        return builder.build();
    }

    /**
     * Builds {@link LinkVanishedMsg}.
     *
     * @param id ProviderId
     * @param linkDescription {@link LinkDescription}
     * @return {@link LinkVanishedMsg}
     */
    private LinkVanishedMsg vanishMsg(ProviderId id,
                                      LinkDescription linkDescription) {

        LinkVanishedMsg.Builder builder = LinkVanishedMsg.newBuilder();
        builder.setProviderId(id.scheme())
            .setLinkDescription(builder.getLinkDescriptionBuilder()
                             .setSrc(translate(linkDescription.src()))
                             .setDst(translate(linkDescription.dst()))
                             .setType(translate(linkDescription.type()))
                             .putAllAnnotations(asMap(linkDescription.annotations()))
                             .build()
                             );
        return builder.build();
    }

    /**
     * Builds {@link LinkVanishedMsg}.
     *
     * @param id ProviderId
     * @param connectPoint {@link ConnectPoint}
     * @return {@link LinkVanishedMsg}
     */
    private LinkVanishedMsg vanishMsg(ProviderId id,
                                      ConnectPoint connectPoint) {

        LinkVanishedMsg.Builder builder = LinkVanishedMsg.newBuilder();
        builder.setProviderId(id.scheme())
            .setConnectPoint(translate(connectPoint));
        return builder.build();
    }

    /**
     * Builds {@link LinkVanishedMsg}.
     *
     * @param id ProviderId
     * @param deviceId {@link DeviceId}
     * @return {@link LinkVanishedMsg}
     */
    private LinkVanishedMsg vanishMsg(ProviderId id, DeviceId deviceId) {

        LinkVanishedMsg.Builder builder = LinkVanishedMsg.newBuilder();
        builder.setProviderId(id.scheme())
            .setDeviceId(deviceId.toString());
        return builder.build();
    }

    /**
     * Translates ONOS object to gRPC message.
     *
     * @param type {@link org.onosproject.net.Link.Type Link.Type}
     * @return gRPC LinkTypeProto
     */
    private LinkTypeProto translate(Type type) {
        switch (type) {
        case DIRECT:
            return LinkTypeProto.DIRECT;
        case EDGE:
            return LinkTypeProto.EDGE;
        case INDIRECT:
            return LinkTypeProto.INDIRECT;
        case OPTICAL:
            return LinkTypeProto.OPTICAL;
        case TUNNEL:
            return LinkTypeProto.TUNNEL;
        case VIRTUAL:
            return LinkTypeProto.VIRTUAL;

        default:
            return LinkTypeProto.DIRECT;

        }
    }

    /**
     * Translates ONOS object to gRPC message.
     *
     * @param cp {@link ConnectPoint}
     * @return gRPC ConnectPointProto
     */
    private ConnectPointProto translate(ConnectPoint cp) {
        return ConnectPointProto.newBuilder()
                .setDeviceId(cp.deviceId().toString())
                .setPortNumber(cp.port().toString())
                .build();
    }

}
