package net.onrc.onos.core.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.core.datastore.DataStoreClient;
import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
import net.onrc.onos.core.datastore.topology.KVLink.STATUS;
import net.onrc.onos.core.datastore.utils.ByteArrayComparator;
import net.onrc.onos.core.datastore.utils.ByteArrayUtil;
import net.onrc.onos.core.datastore.utils.KVObject;
import net.onrc.onos.core.topology.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;
    
    // Assume there is only one ip on a device now.
    private int ip;
    private long lastSeenTime;

    // 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, ":") + "]";
    }
    
	public int getIp() {
		return ip;
	}

	public void setIp(int ip) {
		this.ip = ip;
	}

	public long getLastSeenTime() {
		return lastSeenTime;
	}

	public void setLastSeenTime(long lastSeenTime) {
		this.lastSeenTime = lastSeenTime;
	}
}
