package net.onrc.onos.core.datastore.topology;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import net.onrc.onos.core.datastore.DataStoreClient;
import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
import net.onrc.onos.core.datastore.RCProtos.SwitchProperty;
import net.onrc.onos.core.datastore.utils.KVObject;
import net.onrc.onos.core.topology.SwitchEvent;

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

import com.esotericsoftware.kryo.Kryo;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;

/**
 * Switch object in data store.
 *
 * Note: This class will not maintain invariants.
 *       e.g., It will NOT automatically remove Ports on Switch,
 *       when deleting a Switch.
 */
public class KVSwitch extends KVObject {
    private static final Logger log = LoggerFactory.getLogger(KVSwitch.class);

    private static final ThreadLocal<Kryo> switchKryo = 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_SWITCH_TABLE_NAME = "G:Switch";

    // must not re-order enum members, ordinal will be sent over wire
    public enum STATUS {
        INACTIVE, ACTIVE;
    }

    private final Long dpid;
    private STATUS status;

    public static byte[] getSwitchID(final Long dpid) {
        return SwitchEvent.getSwitchID(dpid).array();
    }

    public static long getDpidFromKey(final byte[] key) {
        return getDpidFromKey(ByteBuffer.wrap(key));
    }

    public static long getDpidFromKey(final ByteBuffer keyBuf) {
        if (keyBuf.getChar() != 'S') {
            throw new IllegalArgumentException("Invalid Switch key");
        }
        return keyBuf.getLong();
    }

    // FIXME specify DPID here, or Should caller specify the key it self?
    // In other words, should layer above have the control of the ID?
    public KVSwitch(final Long dpid) {
        super(DataStoreClient.getClient().getTable(GLOBAL_SWITCH_TABLE_NAME), getSwitchID(dpid));

        this.dpid = dpid;
        this.status = STATUS.INACTIVE;
    }

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

    public static Iterable<KVSwitch> getAllSwitches() {
        return new SwitchEnumerator();
    }

    public static class SwitchEnumerator implements Iterable<KVSwitch> {

        @Override
        public Iterator<KVSwitch> iterator() {
            return new SwitchIterator();
        }
    }

    public static class SwitchIterator extends AbstractObjectIterator<KVSwitch> {

        public SwitchIterator() {
            super(DataStoreClient.getClient().getTable(GLOBAL_SWITCH_TABLE_NAME));
        }

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

    public STATUS getStatus() {
        return status;
    }

    public void setStatus(final STATUS status) {
        this.status = status;
    }

    public Long getDpid() {
        return dpid;
    }

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

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

        SwitchProperty.Builder sw = SwitchProperty.newBuilder();
        sw.setDpid(dpid);
        sw.setStatus(status.ordinal());

        if (!map.isEmpty()) {
            byte[] propMaps = serializePropertyMap(switchKryo.get(), map);
            sw.setValue(ByteString.copyFrom(propMaps));
        }

        return sw.build().toByteArray();
    }

    @Override
    protected boolean deserialize(final byte[] bytes) {
        try {
            boolean success = true;

            SwitchProperty sw = SwitchProperty.parseFrom(bytes);
            byte[] props = sw.getValue().toByteArray();
            success &= deserializePropertyMap(switchKryo.get(), props);
            this.status = STATUS.values()[sw.getStatus()];

            return success;
        } catch (InvalidProtocolBufferException e) {
            log.error("Deserializing Switch: " + this + " failed.", e);
            return false;
        }
    }

    @Override
    public String toString() {
        // TODO output all properties?
        return "[" + this.getClass().getSimpleName()
                + " 0x" + Long.toHexString(dpid) + " STATUS:" + status + "]";
    }

}
