/*
 * 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.drivers.ovsdb;

import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.behaviour.MirroringConfig;
import org.onosproject.net.behaviour.MirroringDescription;
import org.onosproject.net.behaviour.MirroringStatistics;
import org.onosproject.net.behaviour.MirroringName;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbConstant;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbMirror;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static org.onlab.util.Tools.delay;

/**
 * Implementation of mirror config which allows to add, delete and get mirrorings statistics.
 */
public class OvsdbMirroringConfig extends AbstractHandlerBehaviour implements MirroringConfig {

    private static Logger log = LoggerFactory.getLogger(OvsdbMirroringConfig.class);

    /**
     * Adds a mirroring with a given description.
     *
     * @param bridge the bridge name
     * @param mirroringDescription mirroring description
     * @return true if succeeds, or false
     */
    @Override
    public boolean addMirroring(BridgeName bridge, MirroringDescription mirroringDescription) {
        DriverHandler handler = handler();
        OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
        OvsdbMirror mirror = OvsdbMirror.builder(mirroringDescription).build();
        return ovsdbClient.createMirror(bridge.name(), mirror);
    }

    /**
     * Removes a mirroring.
     *
     * @param mirroringName mirroring name
     */
    @Override
    public void deleteMirroring(MirroringName mirroringName) {
        DriverHandler handler = handler();
        OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
        ovsdbClient.dropMirror(mirroringName);
    }

    /**
     * Returns a collection of MirroringStatistics.
     *
     * @return statistics collection
     */
    @Override
    public Collection<MirroringStatistics> getMirroringStatistics() {
        DriverHandler handler = handler();
        OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
        return ovsdbClient.getMirroringStatistics(handler.data().deviceId());
    }

    /**
     * Helper method which is used for getting OvsdbClientService.
     */
    private OvsdbClientService getOvsdbClientService(DriverHandler handler) {

        OvsdbController ovsController = handler.get(OvsdbController.class);
        DeviceService deviceService = handler.get(DeviceService.class);
        DeviceId deviceId = handler.data().deviceId();

        String[] splits = deviceId.toString().split(":");
        if (splits == null || splits.length < 1) {
            log.warn("Wrong deviceId format");
            return null;
        }

        /**
         * Each type of device has to be managed in a different way.
         */
        switch (splits[0]) {
            case "ovsdb":
                OvsdbNodeId nodeId = changeDeviceIdToNodeId(deviceId);
                return ovsController.getOvsdbClient(nodeId);
            case "of":
                String[] mgmtAddress = deviceService.getDevice(deviceId)
                        .annotations().value(AnnotationKeys.MANAGEMENT_ADDRESS).split(":");
                String targetIp = mgmtAddress[0];
                TpPort targetPort = null;
                if (mgmtAddress.length > 1) {
                    targetPort = TpPort.tpPort(Integer.parseInt(mgmtAddress[1]));
                }
                List<OvsdbNodeId> nodeIds = ovsController.getNodeIds().stream()
                        .filter(nodeID -> nodeID.getIpAddress().equals(targetIp))
                        .collect(Collectors.toList());
                if (nodeIds.isEmpty()) {
                    //TODO decide what port?
                    ovsController.connect(IpAddress.valueOf(targetIp),
                                          targetPort == null ? TpPort.tpPort(OvsdbConstant.OVSDBPORT) : targetPort);
                    delay(1000); //FIXME... connect is async
                }
                List<OvsdbClientService> clientServices = ovsController.getNodeIds().stream()
                        .filter(nodeID -> nodeID.getIpAddress().equals(targetIp))
                        .map(ovsController::getOvsdbClient)
                        .filter(cs -> cs.getBridges().stream().anyMatch(b -> dpidMatches(b, deviceId)))
                        .collect(Collectors.toList());
                checkState(!clientServices.isEmpty(), "No clientServices found");
                //FIXME add connection to management address if null --> done ?
                return !clientServices.isEmpty() ? clientServices.get(0) : null;
            default:
                log.warn("Unmanaged device type");
        }
        return null;

    }

    private static boolean dpidMatches(OvsdbBridge bridge, DeviceId deviceId) {
        checkArgument(bridge.datapathId().isPresent());

        String bridgeDpid = "of:" + bridge.datapathId().get();
        String ofDpid = deviceId.toString();
        return bridgeDpid.equals(ofDpid);
    }

    /**
     * OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
     * is used in the core. So DeviceId need be changed to OvsdbNodeId.
     *
     * @param deviceId the device id in ovsdb:ip format
     * @return the ovsdb node id
     */
    private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
        String[] splits = deviceId.toString().split(":");
        if (splits == null || splits.length < 1) {
            return null;
        }
        IpAddress ipAddress = IpAddress.valueOf(splits[1]);
        return new OvsdbNodeId(ipAddress, 0);
    }

}
