package net.onrc.onos.ofcontroller.core.internal;

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

import net.floodlightcontroller.routing.Link;
import net.onrc.onos.graph.DBOperation;
import net.onrc.onos.ofcontroller.core.ILinkStorage;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;

import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.thinkaurelius.titan.core.TitanException;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.pipes.PipeFunction;
import com.tinkerpop.pipes.transform.PathPipe;
import net.onrc.onos.graph.GraphDBManager;

/**
 * This is the class for storing the information of links into CassandraDB
 */
public class LinkStorageImpl implements ILinkStorage {

    protected static Logger log = LoggerFactory.getLogger(LinkStorageImpl.class);
    protected DBOperation dbop;

    /**
     * Update a record in the LinkStorage in a way provided by op.
     *
     * @param link Record of a link to be updated.
     * @param op Operation to be done.
     */
    @Override
    public void update(Link link, DM_OPERATION op) {
        update(link, (LinkInfo) null, op);
    }

    /**
     * Update multiple records in the LinkStorage in a way provided by op.
     *
     * @param links List of records to be updated.
     * @param op Operation to be done.
     */
    @Override
    public void update(List<Link> links, DM_OPERATION op) {
        for (Link lt : links) {
            update(lt, (LinkInfo) null, op);
        }
    }

    /**
     * Update a record of link with meta-information in the LinkStorage in a way
     * provided by op.
     *
     * @param link Record of a link to update.
     * @param linkinfo Meta-information of a link to be updated.
     * @param op Operation to be done.
     */
    @Override
    public void update(Link link, LinkInfo linkinfo, DM_OPERATION op) {
        switch (op) {
            case UPDATE:
            case CREATE:
            case INSERT:
                updateLink(link, linkinfo, op);
                break;
            case DELETE:
                deleteLink(link);
                break;
        }
    }

    /**
     * Perform INSERT/CREATE/UPDATE operation to update the LinkStorage.
     *
     * @param lt Record of a link to be updated.
     * @param linkinfo Meta-information of a link to be updated.
     * @param op Operation to be done. (only INSERT/CREATE/UPDATE is acceptable)
     */
    public void updateLink(Link lt, LinkInfo linkinfo, DM_OPERATION op) {
        IPortObject vportSrc = null, vportDst = null;

        log.trace("updateLink(): op {} {} {}", new Object[]{op, lt, linkinfo});

        try {
            // get source port vertex
            String dpid = HexString.toHexString(lt.getSrc());
            short port = lt.getSrcPort();
            vportSrc = dbop.searchPort(dpid, port);

            // get dest port vertex
            dpid = HexString.toHexString(lt.getDst());
            port = lt.getDstPort();
            vportDst = dbop.searchPort(dpid, port);

            if (vportSrc != null && vportDst != null) {
                // check if the link exists

                Iterable<IPortObject> currPorts = vportSrc.getLinkedPorts();
                List<IPortObject> currLinks = new ArrayList<IPortObject>();
                for (IPortObject V : currPorts) {
                    currLinks.add(V);
                }

                if (currLinks.contains(vportDst)) {
                    // TODO: update linkinfo
                    if (op.equals(DM_OPERATION.INSERT) || op.equals(DM_OPERATION.CREATE)) {
                        log.debug("addOrUpdateLink(): failed link exists {} {} src {} dst {}",
                                new Object[]{op, lt, vportSrc, vportDst});
                    }
                } else {
                    vportSrc.setLinkPort(vportDst);

                    dbop.commit();
                    log.debug("updateLink(): link added {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
                }
            } else {
                log.error("updateLink(): failed invalid vertices {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
                dbop.rollback();
            }
        } catch (TitanException e) {
            /*
             * retry till we succeed?
             */
            e.printStackTrace();
            log.error("updateLink(): titan exception {} {} {}", new Object[]{op, lt, e.toString()});
        }
    }

    /**
     * Delete multiple records in LinkStorage.
     *
     * @param links List of records to be deleted.
     */
    @Override
    public void deleteLinks(List<Link> links) {

        for (Link lt : links) {
            deleteLink(lt);
        }
    }

    /**
     * Delete a record in the LinkStorage.
     *
     * @param lt Record to be deleted.
     */
    @Override
    public void deleteLink(Link lt) {
        IPortObject vportSrc = null, vportDst = null;
        int count = 0;

        log.debug("deleteLink(): {}", lt);

        try {
            // get source port vertex
            String dpid = HexString.toHexString(lt.getSrc());
            short port = lt.getSrcPort();
            vportSrc = dbop.searchPort(dpid, port);

            // get dst port vertex
            dpid = HexString.toHexString(lt.getDst());
            port = lt.getDstPort();
            vportDst = dbop.searchPort(dpid, port);
            // FIXME: This needs to remove all edges

            if (vportSrc != null && vportDst != null) {

                /*      		for (Edge e : vportSrc.asVertex().getEdges(Direction.OUT)) {
                 log.debug("deleteLink(): {} in {} out {}", 
                 new Object[]{e.getLabel(), e.getVertex(Direction.IN), e.getVertex(Direction.OUT)});
                 if (e.getLabel().equals("link") && e.getVertex(Direction.IN).equals(vportDst)) {
                 graph.removeEdge(e);
                 count++;
                 }
                 }*/
                vportSrc.removeLink(vportDst);
                dbop.commit();
                log.debug("deleteLink(): deleted edges src {} dst {}", new Object[]{
                    lt, vportSrc, vportDst});

            } else {
                log.error("deleteLink(): failed invalid vertices {} src {} dst {}", new Object[]{lt, vportSrc, vportDst});
                dbop.rollback();
            }

        } catch (TitanException e) {
            /*
             * retry till we succeed?
             */
            log.error("deleteLink(): titan exception {} {}", new Object[]{lt, e.toString()});
            dbop.rollback();
            e.printStackTrace();
        }
    }

    /**
     * Get list of all links connected to the port specified by given DPID and
     * port number.
     *
     * @param dpid DPID of desired port.
     * @param port Port number of desired port.
     * @return List of links. Empty list if no port was found.
     */
    // TODO: Fix me
    @Override
    public List<Link> getLinks(Long dpid, short port) {
        List<Link> links = new ArrayList<Link>();

        IPortObject srcPort = dbop.searchPort(HexString.toHexString(dpid), port);
        ISwitchObject srcSw = srcPort.getSwitch();

        if (srcSw != null && srcPort != null) {
            for (IPortObject dstPort : srcPort.getLinkedPorts()) {
                ISwitchObject dstSw = dstPort.getSwitch();
                Link link = new Link(HexString.toLong(srcSw.getDPID()),
                        srcPort.getNumber(),
                        HexString.toLong(dstSw.getDPID()),
                        dstPort.getNumber());

                links.add(link);
            }
        }

        return links;
    }

    /**
     * Initialize the object. Open LinkStorage using given configuration file.
     *
     * @param conf Path (absolute path for now) to configuration file.
     */
    @Override
    public void init(final String dbStore, final String conf) {
        this.dbop = GraphDBManager.getDBOperation(dbStore, conf);
    }

    /**
     * Delete records of the links connected to the port specified by given DPID
     * and port number.
     *
     * @param dpid DPID of desired port.
     * @param port Port number of desired port.
     */
    // TODO: Fix me
    @Override
    public void deleteLinksOnPort(Long dpid, short port) {
        List<Link> linksToDelete = getLinks(dpid, port);

        for (Link l : linksToDelete) {
            deleteLink(l);
        }
    }

    /**
     * Get list of all links connected to the switch specified by given DPID.
     *
     * @param dpid DPID of desired switch.
     * @return List of links. Empty list if no port was found.
     */
    // TODO: Fix me
    @Override
    public List<Link> getLinks(String dpid) {
        List<Link> links = new ArrayList<Link>();

        ISwitchObject srcSw = dbop.searchSwitch(dpid);

        if (srcSw != null) {
            for (IPortObject srcPort : srcSw.getPorts()) {
                for (IPortObject dstPort : srcPort.getLinkedPorts()) {
                    ISwitchObject dstSw = dstPort.getSwitch();
                    if (dstSw != null) {
                        Link link = new Link(HexString.toLong(srcSw.getDPID()),
                                srcPort.getNumber(),
                                HexString.toLong(dstSw.getDPID()),
                                dstPort.getNumber());
                        links.add(link);
                    }
                }
            }
        }

        return links;
    }

    /**
     * Get list of all links whose state is ACTIVE.
     *
     * @return List of active links. Empty list if no port was found.
     */
    public List<Link> getActiveLinks() {
        Iterable<ISwitchObject> switches = dbop.getActiveSwitches();

        List<Link> links = new ArrayList<Link>();

        for (ISwitchObject srcSw : switches) {
            for (IPortObject srcPort : srcSw.getPorts()) {
                for (IPortObject dstPort : srcPort.getLinkedPorts()) {
                    ISwitchObject dstSw = dstPort.getSwitch();

                    if (dstSw != null && dstSw.getState().equals("ACTIVE")) {
                        links.add(new Link(HexString.toLong(srcSw.getDPID()),
                                srcPort.getNumber(),
                                HexString.toLong(dstSw.getDPID()),
                                dstPort.getNumber()));
                    }
                }
            }
        }

        return links;
    }

    static class ExtractLink implements PipeFunction<PathPipe<Vertex>, Link> {

        @Override
        public Link compute(PathPipe<Vertex> pipe) {
            // TODO Auto-generated method stub
            long s_dpid = 0;
            long d_dpid = 0;
            short s_port = 0;
            short d_port = 0;
            List<Vertex> V = new ArrayList<Vertex>();
            V = pipe.next();
            Vertex src_sw = V.get(0);
            Vertex dest_sw = V.get(3);
            Vertex src_port = V.get(1);
            Vertex dest_port = V.get(2);
            s_dpid = HexString.toLong((String) src_sw.getProperty("dpid"));
            d_dpid = HexString.toLong((String) dest_sw.getProperty("dpid"));
            s_port = (Short) src_port.getProperty("number");
            d_port = (Short) dest_port.getProperty("number");

            Link l = new Link(s_dpid, s_port, d_dpid, d_port);

            return l;
        }
    }

    /**
     * Finalize the object.
     */
    public void finalize() {
        close();
    }

    /**
     * Close LinkStorage.
     */
    @Override
    public void close() {
        // TODO Auto-generated method stub
//		graph.shutdown();		
    }
}
