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.getNumber());
            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.getNumber());
            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.getNumber());
        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.getNumber());
        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().getNumber(),
                link.getDst().getDpid(),
                link.getDst().getNumber());

        // 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().getNumber(),
                linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
        rcLink.forceDelete();

        return true;
    }

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

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

        for (SwitchPort sp : device.getAttachmentPoints()) {
            byte[] portId = KVPort.getPortID(sp.getDpid(), sp.getNumber());
            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 removeDevice(DeviceEvent device) {
        log.debug("Removing device into DB. mac {}", device.getMac());

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

        return true;
    }
}
