/**
 *    Copyright 2011, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
 *
 *    Licensed under the Apache License, Version 2.0 (the "License"); you may
 *    not use this file except in compliance with the License. You may obtain
 *    a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 *    License for the specific language governing permissions and limitations
 *    under the License.
 **/

package net.floodlightcontroller.core.web;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.annotations.LogMessageDoc;
import net.onrc.onos.core.drivermanager.OFSwitchImplSpringOpenTTP;

import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsRequest;
import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.util.HexString;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Base class for server resources related to switches
 *
 * @author readams
 */

public class SwitchResourceBase extends ServerResource {
    protected final static Logger log = LoggerFactory.getLogger(SwitchResourceBase.class);

    public enum REQUESTTYPE {
        OFSTATS,
        OFFEATURES
    }

    @Override
    protected void doInit() throws ResourceException {
        super.doInit();

    }

    @LogMessageDoc(level = "ERROR",
            message = "Failure retrieving statistics from switch {switch}",
            explanation = "An error occurred while retrieving statistics" +
                    "from the switch",
                    recommendation = LogMessageDoc.CHECK_SWITCH + " " +
                            LogMessageDoc.GENERIC_ACTION)

    protected List<?> getSwitchStatistics(long switchId,
            OFStatsType statType) {
        IFloodlightProviderService floodlightProvider =
                (IFloodlightProviderService) getContext().getAttributes().
                get(IFloodlightProviderService.class.getCanonicalName());

        IOFSwitch sw = floodlightProvider.getSwitches().get(switchId);
        Future<List<OFStatsReply>> future;
        List<OFStatsReply> values = null;
        if (sw != null) {
            OFStatsRequest<?> req = null;
            if (statType == OFStatsType.FLOW) {
                log.debug("Switch Flow Stats req sent for switch {}",
                        sw.getStringId());
                OFMatchV3 match = sw.getFactory().buildMatchV3()
                        .setOxmList(OFOxmList.EMPTY).build();
                req = sw.getFactory()
                        .buildFlowStatsRequest()
                        .setMatch(match)
                        .setOutPort(OFPort.ANY)
                        .setTableId(TableId.ALL)
                        .setXid(sw.getNextTransactionId()).build();
                List<OFFlowStatsEntryMod> flowStats = new ArrayList<OFFlowStatsEntryMod>();
                try {
                    future = sw.getStatistics(req);
                    values = future.get(10, TimeUnit.SECONDS);
                    for (OFFlowStatsEntry entry : ((OFFlowStatsReply)values.get(0)).getEntries()) {
                        OFFlowStatsEntryMod entryMod = new OFFlowStatsEntryMod(entry);
                        flowStats.add(entryMod);
                    }
                    log.debug("Switch flow Stats Entries from switch {} are {}",
                            sw.getStringId(), flowStats);
                } catch (Exception e) {
                    log.error("Failure retrieving statistics from switch " + sw, e);
                }
                return flowStats;
            }
            else if (statType == OFStatsType.PORT){
                log.debug("Switch Port Stats: req sent for all "
                        + "ports in switch {}", sw.getStringId());
                List<OFPortStatsEntryMod> portStats = null;
                req = sw.getFactory()
                        .buildPortStatsRequest()
                        .setPortNo(OFPort.ANY).setXid
                        (sw.getNextTransactionId()).build();
                try {
                    future = sw.getStatistics(req);
                    values = future.get(10, TimeUnit.SECONDS);
                    portStats = new ArrayList<OFPortStatsEntryMod>();
                    for (OFPortStatsEntry entry : ((OFPortStatsReply)values.get(0)).getEntries()) {
                        OFPortStatsEntryMod entryMod = new OFPortStatsEntryMod(entry);
                        portStats.add(entryMod);
                    }
                    log.debug("Switch Port Stats Entries from switch {} are {}",
                            sw.getStringId(), portStats);
                } catch (Exception e) {
                    log.error("Failure retrieving statistics from switch " + sw, e);
                }
                return portStats;
            }
            else if (statType == OFStatsType.GROUP){
                log.debug("Switch Group Stats: req sent for all "
                        + "ports in switch {}", sw.getStringId());
                req = sw.getFactory().buildGroupStatsRequest().setXid
                        (sw.getNextTransactionId()).build();
                List<OFGroupStatsEntryMod> groupStats = new ArrayList<OFGroupStatsEntryMod>();
                try {
                    future = sw.getStatistics(req);
                    values = future.get(10, TimeUnit.SECONDS);
                    for (OFGroupStatsEntry entry : ((OFGroupStatsReply)values.get(0)).getEntries()) {
                        OFGroupStatsEntryMod entryMod = new OFGroupStatsEntryMod(entry);
                        groupStats.add(entryMod);
                    }
                    log.debug("Switch Group Stats Entries from switch {} are {}",
                            sw.getStringId(), groupStats);
                } catch (Exception e) {
                    log.error("Failure retrieving statistics from switch " + sw, e);
                }
                return groupStats;
            }
            else if (statType == OFStatsType.GROUP_DESC){
                log.debug("Switch Group Desc Stats: req sent for all "
                        + "ports in switch {}", sw.getStringId());
                List<OFGroupDescStatsEntryMod> GroupDescStats= new ArrayList<OFGroupDescStatsEntryMod>();
                req = sw.getFactory().buildGroupDescStatsRequest().setXid
                        (sw.getNextTransactionId()).build();
                try {
                    future = sw.getStatistics(req);
                    values = future.get(10, TimeUnit.SECONDS);
                    for (OFGroupDescStatsEntry entry : ((OFGroupDescStatsReply)values.get(0)).getEntries()) {
                        OFGroupDescStatsEntryMod entryMod = new OFGroupDescStatsEntryMod(entry);
                        GroupDescStats.add(entryMod);
                    }
                    log.debug("Switch Group_Desc Stats Entries from switch {} are {}",
                            sw.getStringId(), GroupDescStats);
                } catch (Exception e) {
                    log.error("Failure retrieving statistics from switch " + sw, e);
                }
                return GroupDescStats;
            }
            /*else if (statType == OFStatisticsType.AGGREGATE) {
                OFAggregateStatisticsRequest specificReq = new OFAggregateStatisticsRequest();
                OFMatch match = new OFMatch();
                match.setWildcards(0xffffffff);
                specificReq.setMatch(match);
                specificReq.setOutPort(OFPort.OFPP_NONE.getValue());
                specificReq.setTableId((byte) 0xff);
                req.setStatistics(Collections.singletonList((OFStatistics) specificReq));
                requestLength += specificReq.getLength();
            } /*else if (statType == OFStatisticsType.QUEUE) {
                OFQueueStatisticsRequest specificReq = new OFQueueStatisticsRequest();
                specificReq.setPortNumber(OFPort.OFPP_ALL.getValue());
                // LOOK! openflowj does not define OFPQ_ALL! pulled this from openflow.h
                // note that I haven't seen this work yet though...
                specificReq.setQueueId(0xffffffff);
                req.setStatistics(Collections.singletonList((OFStatistics) specificReq));
                requestLength += specificReq.getLength();
            } else if (statType == OFStatisticsType.DESC ||
                    statType == OFStatisticsType.TABLE) {
                // pass - nothing todo besides set the type above
            }*/
            // XXX S fix when we fix stats
            try {
                future = sw.getStatistics(req);
                values = future.get(10, TimeUnit.SECONDS);
            } catch (Exception e) {
                log.error("Failure retrieving statistics from switch " + sw, e);
            }
        }
        return values;
    }

    protected Object getSwitchStatistics(String switchId, OFStatsType statType) {
        return getSwitchStatistics(HexString.toLong(switchId), statType);
    }
    //TODO: Java doc
    protected List<?> getSwitchStatisticsForTable(long switchId,
            OFStatsType statType, String tableType) {
        IFloodlightProviderService floodlightProvider =
                (IFloodlightProviderService) getContext().getAttributes().
                get(IFloodlightProviderService.class.getCanonicalName());
        IOFSwitch sw = floodlightProvider.getSwitches().get(switchId);
        Future<List<OFStatsReply>> future;
        List<OFStatsReply> values = null;
        //getting tableId from CPqD driver
        TableId tableId;
        if (sw != null) {
            if ((tableId = ((OFSwitchImplSpringOpenTTP) sw).getTableId(tableType)) == null) {
                log.error("Invalid tableType {} " + tableType);
                return null;
            }
            OFStatsRequest<?> req = null;
            if (statType == OFStatsType.FLOW) {
                log.debug("Switch Flow Stats req for table {} sent to switch {}",
                        tableType,sw.getStringId());
                OFMatchV3 match = sw.getFactory().buildMatchV3()
                        .setOxmList(OFOxmList.EMPTY).build();
                req = sw.getFactory()
                        .buildFlowStatsRequest()
                        .setMatch(match)
                        .setOutPort(OFPort.ANY)
                        .setTableId(tableId)
                        .setXid(sw.getNextTransactionId()).build();
                List<OFFlowStatsEntryMod> flowStats = new ArrayList<OFFlowStatsEntryMod>();
                try {
                    future = sw.getStatistics(req);
                    values = future.get(10, TimeUnit.SECONDS);
                    for (OFFlowStatsEntry entry : ((OFFlowStatsReply)values.get(0)).getEntries()) {
                        OFFlowStatsEntryMod entryMod = new OFFlowStatsEntryMod(entry);
                        flowStats.add(entryMod);
                    }
                    log.debug("Switch flow Stats Entries for table {} from switch {} are {}",
                            tableType, sw.getStringId(), flowStats);
                } catch (Exception e) {
                    log.error("Failure retrieving per table statistics from switch " + sw, e);
                }
                return flowStats;
            }
        }
        //should never get to this point
        log.error("Failure retrieving  {} table statistics from switch {}",tableType, sw);
        return null;
    }

    protected OFFeaturesReply getSwitchFeaturesReply(long switchId) {
        IFloodlightProviderService floodlightProvider =
                (IFloodlightProviderService) getContext().getAttributes().
                get(IFloodlightProviderService.class.getCanonicalName());

        IOFSwitch sw = floodlightProvider.getSwitches().get(switchId);
        //uture<OFFeaturesReply> future;
        OFFeaturesReply featuresReply = null;
        if (sw != null) {
            // XXX S fix when we fix stats
            try {
                //future = sw.getFeaturesReplyFromSwitch();
                //featuresReply = future.get(10, TimeUnit.SECONDS);
            } catch (Exception e) {
                log.error("Failure getting features reply from switch" + sw, e);
            }
        }

        return featuresReply;
    }

    protected OFFeaturesReply getSwitchFeaturesReply(String switchId) {
        return getSwitchFeaturesReply(HexString.toLong(switchId));
    }

}
