package net.onrc.onos.datastore.topology;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import net.onrc.onos.datastore.DataStoreClient;
import net.onrc.onos.datastore.IKVTable.IKVEntry;
import net.onrc.onos.datastore.topology.KVLink.STATUS;
import net.onrc.onos.datastore.utils.ByteArrayComparator;
import net.onrc.onos.datastore.utils.ByteArrayUtil;
import net.onrc.onos.datastore.utils.KVObject;
import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;

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

import com.esotericsoftware.kryo.Kryo;

/**
 * Device object.
 *
 * TODO switch to ProtoBuf, etc.
 */
public class KVDevice extends KVObject {
    private static final Logger log = LoggerFactory.getLogger(KVDevice.class);

    private static final ThreadLocal<Kryo> deviceKryo = new ThreadLocal<Kryo>() {
	@Override
	protected Kryo initialValue() {
	    Kryo kryo = new Kryo();
	    kryo.setRegistrationRequired(true);
	    kryo.setReferences(false);
	    kryo.register(byte[].class);
	    kryo.register(byte[][].class);
	    kryo.register(HashMap.class);
	    // TODO check if we should explicitly specify EnumSerializer
	    kryo.register(STATUS.class);
	    return kryo;
	}
    };

    public static final String GLOBAL_DEVICE_TABLE_NAME = "G:Device";

    // FIXME these should be Enum or some number, not String
    private static final String PROP_MAC = "mac";
    private static final String PROP_PORT_IDS = "port-ids";

    private final byte[] mac;
    private TreeSet<byte[]> portIds;
    private transient boolean isPortIdsModified;

    // Assuming mac is unique cluster-wide
    public static byte[] getDeviceID(final byte[] mac) {
	return DeviceEvent.getDeviceID(mac).array();
    }

    public static byte[] getMacFromKey(final byte[] key) {
	ByteBuffer keyBuf = ByteBuffer.wrap(key);
	if (keyBuf.getChar() != 'D') {
	    throw new IllegalArgumentException("Invalid Device key");
	}
	byte[] mac = new byte[keyBuf.remaining()];
	keyBuf.get(mac);
	return mac;
    }

    public KVDevice(final byte[] mac) {
	super(DataStoreClient.getClient().getTable(GLOBAL_DEVICE_TABLE_NAME), getDeviceID(mac));

	this.mac = mac;
	this.portIds = new TreeSet<>(ByteArrayComparator.BYTEARRAY_COMPARATOR);
	this.isPortIdsModified = true;
    }

    /**
     * Get an instance from Key.
     *
     * @note You need to call `read()` to get the DB content.
     * @param key
     * @return
     */
    public static KVDevice createFromKey(final byte[] key) {
	return new KVDevice(getMacFromKey(key));
    }

    public static Iterable<KVDevice> getAllDevices() {
	return new DeviceEnumerator();
    }

    public static class DeviceEnumerator implements Iterable<KVDevice> {

	@Override
	public Iterator<KVDevice> iterator() {
	    return new DeviceIterator();
	}
    }

    public static class DeviceIterator extends AbstractObjectIterator<KVDevice> {

	public DeviceIterator() {
	    super(DataStoreClient.getClient().getTable(GLOBAL_DEVICE_TABLE_NAME));
	}

	@Override
	public KVDevice next() {
	    IKVEntry o = enumerator.next();
	    KVDevice e = KVDevice.createFromKey(o.getKey());
	    e.deserialize(o.getValue(), o.getVersion());
	    return e;
	}
    }

    public byte[] getMac() {
	// TODO may need to clone() to be sure this object will be immutable.
	return mac;
    }

    public byte[] getId() {
	return getKey();
    }

    public void addPortId(final byte[] portId) {
	// TODO: Should we copy portId, or reference is OK.
	isPortIdsModified |= portIds.add(portId);
    }

    public void removePortId(final byte[] portId) {
	isPortIdsModified |= portIds.remove(portId);
    }

    public void emptyPortIds() {
	portIds.clear();
	this.isPortIdsModified = true;
    }

    public void addAllToPortIds(final Collection<byte[]> portIds) {
	// TODO: Should we copy portId, or reference is OK.
	isPortIdsModified |= this.portIds.addAll(portIds);
    }

    /**
     *
     * @return Unmodifiable Set view of all the PortIds;
     */
    public Set<byte[]> getAllPortIds() {
	return Collections.unmodifiableSet(portIds);
    }

    @Override
    public byte[] serialize() {
	Map<Object, Object> map = getPropertyMap();

	map.put(PROP_MAC, mac);
	if (isPortIdsModified) {
	    byte[][] portIdArray = new byte[portIds.size()][];
	    map.put(PROP_PORT_IDS, portIds.toArray(portIdArray));
	    isPortIdsModified = false;
	}

	return serializePropertyMap(deviceKryo.get(), map);
    }

    @Override
    protected boolean deserialize(final byte[] bytes) {
	boolean success = deserializePropertyMap(deviceKryo.get(), bytes);
	if (!success) {
	    log.error("Deserializing Link: " + this + " failed.");
	    return false;
	}
	Map<Object, Object> map = this.getPropertyMap();

	if (this.portIds == null) {
	    this.portIds = new TreeSet<>(
		    ByteArrayComparator.BYTEARRAY_COMPARATOR);
	}
	byte[][] portIdArray = (byte[][]) map.get(PROP_PORT_IDS);
	if (portIdArray != null) {
	    this.portIds.clear();
	    this.portIds.addAll(Arrays.asList(portIdArray));
	    isPortIdsModified = false;
	} else {
	    // trigger write on next serialize
	    isPortIdsModified = true;
	}

	return success;
    }

    @Override
    public String toString() {
	// TODO output all properties?
	return "[" + this.getClass().getSimpleName()
		+ " " + ByteArrayUtil.toHexStringBuffer(mac, ":") + "]";
    }
}
