package net.onrc.onos.apps.segmentrouting.web;



import static net.onrc.onos.core.topology.web.TopologyResource.eval;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.MutableTopology;
import net.onrc.onos.core.topology.Port;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.util.Dpid;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.projectfloodlight.openflow.util.HexString;
import org.restlet.representation.Representation;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
/**
 * Base class for return router statistics
 *
 */
public class RouterStatisticsResource extends ServerResource {
    /**
     * Gets the switches/routers and ports information from the network topology.
     *
     * @return a Representation of a Collection of switches/routers from the network
     * topology. Each switch contains the switch ports.
     */
    @Get("json")
    public Representation retrieve() {
        String routerId = (String) getRequestAttributes().get("routerId");
        String statsType = (String) getRequestAttributes().get("statsType");
        ITopologyService topologyService =
                (ITopologyService) getContext().getAttributes()
                .get(ITopologyService.class.getCanonicalName());

        MutableTopology mutableTopology = topologyService.getTopology();
        mutableTopology.acquireReadLock();
        try {
            if (routerId == null && statsType == null){
                return eval(toRepresentation(mutableTopology.getSwitches(), null));
        }
            else if(routerId != null && statsType.equals("port")){
                Switch sw = mutableTopology
                .getSwitch(new Dpid(HexString.toLong(routerId)));
                if(sw ==null){
                    //TODO: Add exception
                    return null;
                }
                Map <String, List<SegmentRouterPortInfo>> result = new HashMap <String, List<SegmentRouterPortInfo>>();
                List<SegmentRouterPortInfo> listPortInfo = new ArrayList<SegmentRouterPortInfo>();
                Collection<Port> portList =sw.getPorts();
                String subnets = null;
                if (sw.getAllStringAttributes().containsKey("subnets")){
                    subnets = sw.getAllStringAttributes().get("subnets");
                    JSONArray subnetArray = JSONArray.fromObject(subnets);
                    Iterator<Port> pI = portList.iterator();
                    while(pI.hasNext()){
                        Port p = pI.next();
                        Iterator<?> sI = subnetArray.iterator();
                        String subnet = null;
                        while(sI.hasNext()){
                            JSONObject portSubnetIp = (JSONObject) sI.next();
                            subnet = null;
                            if(portSubnetIp.getString("portNo").equals(p.getNumber().toString())){
                                subnet = portSubnetIp.getString("subnetIp");
                                break;
                            }
                        }
                        listPortInfo.add( new SegmentRouterPortInfo(subnet,p));
                    }
                    result.put(routerId, listPortInfo);
                    return eval(toRepresentation(result,null));
                }
                else{
                    Iterator<Port> pI = portList.iterator();
                    while(pI.hasNext()){
                        Port p = pI.next();
                        String subnet = null;
                        listPortInfo.add( new SegmentRouterPortInfo(subnet,p));
                    }
                    result.put(routerId, listPortInfo);
                    return eval(toRepresentation(result,null));
                }
            }
        } finally {
            mutableTopology.releaseReadLock();
        }
    //Should Never get to this point.
    return null;
    }
}
