package net.onrc.onos.core.topology;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import net.onrc.onos.core.datastore.DataStoreClient;
import net.onrc.onos.core.datastore.IKVClient;
import net.onrc.onos.core.datastore.topology.KVDevice;
import net.onrc.onos.core.datastore.topology.KVLink;
import net.onrc.onos.core.datastore.topology.KVPort;
import net.onrc.onos.core.datastore.topology.KVPort.STATUS;
import net.onrc.onos.core.datastore.topology.KVSwitch;
import net.onrc.onos.core.datastore.utils.KVObject;
import net.onrc.onos.core.datastore.utils.KVObject.WriteOp;
import net.onrc.onos.core.util.SwitchPort;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Contains methods which write topology events into the key-value data store.
 */
public class TopologyDatastore {
    private static final Logger log = LoggerFactory.getLogger(TopologyDatastore.class);

    /**
     * Add a switch to the database.
     *
     * @param sw         the switch to add.
     * @param portEvents the corresponding switch ports to add.
     * @return true on success, otherwise false.
     */
    public boolean addSwitch(SwitchEvent sw,
                             Collection<PortEvent> portEvents) {
        log.debug("Adding switch {}", sw);
        ArrayList<WriteOp> groupOp = new ArrayList<>();

        KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
        rcSwitch.setStatus(KVSwitch.STATUS.ACTIVE);

        IKVClient client = DataStoreClient.getClient();

        // XXX Is ForceCreating Switch on DB OK here?
        // If ForceCreating, who ever is calling this method needs
        // to assure that DPID is unique cluster-wide, etc.
        groupOp.add(rcSwitch.forceCreateOp(client));

        for (PortEvent portEvent : portEvents) {
            KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getPortNumber());
            rcPort.setStatus(KVPort.STATUS.ACTIVE);

            groupOp.add(rcPort.forceCreateOp(client));
        }

        boolean failed = KVObject.multiWrite(groupOp);

        if (failed) {
            log.error("Adding Switch {} and its ports failed.", sw.getDpid());
            for (WriteOp op : groupOp) {
                log.debug("Operation:{} for {} - Result:{}", op.getOperation(), op.getObject(), op.getStatus());

                // If we changed the operation from ForceCreate to
                // Conditional operation (Create/Update) then we should retry here.
            }
        }
        return !failed;
    }

    /**
     * Update a switch as inactive in the database.
     *
     * @param sw         the switch to update.
     * @param portEvents the corresponding switch ports to update.
     * @return true on success, otherwise false.
     */
    public boolean deactivateSwitch(SwitchEvent sw,
                                    Collection<PortEvent> portEvents) {
        log.debug("Deactivating switch {}", sw);
        KVSwitch rcSwitch = new KVSwitch(sw.getDpid());

        IKVClient client = DataStoreClient.getClient();

        List<WriteOp> groupOp = new ArrayList<>();
        rcSwitch.setStatus(KVSwitch.STATUS.INACTIVE);

        groupOp.add(rcSwitch.forceCreateOp(client));

        for (PortEvent portEvent : portEvents) {
            KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getPortNumber());
            rcPort.setStatus(KVPort.STATUS.INACTIVE);

            groupOp.add(rcPort.forceCreateOp(client));
        }

        boolean failed = KVObject.multiWrite(groupOp);

        return !failed;
    }

    /**
     * Add a port to the database.
     *
     * @param port the port to add.
     * @return true on success, otherwise false.
     */
    public boolean addPort(PortEvent port) {
        log.debug("Adding port {}", port);

        KVPort rcPort = new KVPort(port.getDpid(), port.getPortNumber());
        rcPort.setStatus(KVPort.STATUS.ACTIVE);
        rcPort.forceCreate();
        // TODO add description into KVPort
        //rcPort.setDescription(port.getDescription());

        return true;
    }

    /**
     * Update a port as inactive in the database.
     *
     * @param port the port to update.
     * @return true on success, otherwise false.
     */
    public boolean deactivatePort(PortEvent port) {
        log.debug("Deactivating port {}", port);

        KVPort rcPort = new KVPort(port.getDpid(), port.getPortNumber());
        rcPort.setStatus(STATUS.INACTIVE);

        rcPort.forceCreate();

        return true;
    }

    /**
     * Add a link to the database.
     *
     * @param link the link to add.
     * @return true on success, otherwise false.
     */
    public boolean addLink(LinkEvent link) {
        log.debug("Adding link {}", link);

        KVLink rcLink = new KVLink(link.getSrc().getDpid(),
                link.getSrc().getPortNumber(),
                link.getDst().getDpid(),
                link.getDst().getPortNumber());

        // XXX This method is called only by discovery,
        // which means what we are trying to write currently is the truth
        // so we can force write here
        //
        // TODO: We need to check for errors
        rcLink.setStatus(KVLink.STATUS.ACTIVE);
        rcLink.forceCreate();

        return true;                    // Success
    }

    public boolean removeLink(LinkEvent linkEvent) {
        log.debug("Removing link {}", linkEvent);

        KVLink rcLink = new KVLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getPortNumber(),
                linkEvent.getDst().getDpid(), linkEvent.getDst().getPortNumber());
        rcLink.forceDelete();

        return true;
    }

    /**
     * Add a device to the database.
     *
     * @param device the device to add.
     * @return true on success, otherwise false.
     */
    public boolean addHost(HostEvent device) {
        log.debug("Adding host into DB. mac {}", device.getMac());

        KVDevice rcDevice = new KVDevice(device.getMac().toBytes());

        for (SwitchPort sp : device.getAttachmentPoints()) {
            byte[] portId = KVPort.getPortID(sp.getDpid(), sp.getPortNumber());
            rcDevice.addPortId(portId);
        }

        rcDevice.forceCreate();

        return true;
    }

    /**
     * Remove a device from the database.
     *
     * @param device the device to remove.
     * @return true on success, otherwise false.
     */
    public boolean removeHost(HostEvent device) {
        log.debug("Removing host into DB. mac {}", device.getMac());

        KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
        rcDevice.forceDelete();

        return true;
    }
}
