/*
 * Copyright 2016 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.store.primitives.impl;

import static com.google.common.base.Preconditions.checkNotNull;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Map;

import org.onlab.packet.IpAddress;
import org.onosproject.cluster.PartitionId;
import org.onosproject.store.cluster.messaging.Endpoint;
import org.onosproject.store.cluster.messaging.MessagingService;

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;

import io.atomix.catalyst.transport.Address;
import io.atomix.catalyst.transport.Client;
import io.atomix.catalyst.transport.Server;
import io.atomix.catalyst.transport.Transport;

/**
 * Custom {@link Transport transport} for Copycat interactions
 * built on top of {@link MessagingService}.
 *
 * @see CopycatTransportServer
 * @see CopycatTransportClient
 */
public class CopycatTransport implements Transport {

    /**
     * Transport Mode.
     */
    public enum Mode {
        /**
         * Signifies transport for client {@literal ->} server interaction.
         */
        CLIENT,

        /**
         * Signified transport for server {@literal ->} server interaction.
         */
        SERVER
    }

    private final Mode mode;
    private final PartitionId partitionId;
    private final MessagingService messagingService;
    private static final Map<Address, Endpoint> EP_LOOKUP_CACHE = Maps.newConcurrentMap();
    private static final Map<Endpoint, Address> ADDRESS_LOOKUP_CACHE = Maps.newConcurrentMap();

    public CopycatTransport(Mode mode, PartitionId partitionId, MessagingService messagingService) {
        this.mode = checkNotNull(mode);
        this.partitionId = checkNotNull(partitionId);
        this.messagingService = checkNotNull(messagingService);
    }

    @Override
    public Client client() {
        return new CopycatTransportClient(partitionId,
                                          messagingService,
                                          mode);
    }

    @Override
    public Server server() {
        return new CopycatTransportServer(partitionId,
                                          messagingService);
    }

    /**
     * Maps {@link Address address} to {@link Endpoint endpoint}.
     * @param address
     * @return end point
     */
    public static Endpoint toEndpoint(Address address) {
        return EP_LOOKUP_CACHE.computeIfAbsent(address, a -> {
            try {
                Endpoint endpoint = new Endpoint(IpAddress.valueOf(InetAddress.getByName(a.host())), a.port());
                ADDRESS_LOOKUP_CACHE.putIfAbsent(endpoint, address);
                return endpoint;
            } catch (UnknownHostException e) {
                Throwables.propagate(e);
                return null;
            }
        });
    }

    /**
     * Maps {@link Endpoint endpoint} to {@link Address address}.
     * @param endpoint end point
     * @return address
     */
    public static Address toAddress(Endpoint endpoint) {
        return ADDRESS_LOOKUP_CACHE.computeIfAbsent(endpoint, ep -> {
            try {
                InetAddress host = InetAddress.getByAddress(endpoint.host().toOctets());
                int port = endpoint.port();
                Address address = new Address(new InetSocketAddress(host, port));
                EP_LOOKUP_CACHE.putIfAbsent(address, endpoint);
                return address;
            } catch (UnknownHostException e) {
                Throwables.propagate(e);
                return null;
            }
        });
    }
}
