/*
 * Copyright (c) 2015 Ziver
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package wa.server.plugin.hwstatus;

import org.hyperic.sigar.*;
import org.hyperic.sigar.cmd.Shell;
import wa.server.plugin.WAStatus;
import zutil.io.file.FileUtil;
import zutil.net.ThroughputCalculator;
import zutil.parser.DataNode;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Ziver on 2015-04-28.
 */
public class NetStatus implements WAStatus{
    private int nextId;
    private HashMap<String,Integer> idMap = new HashMap<String,Integer>();

    private HashMap<String,ThroughputCalculator> txMap = new HashMap<String,ThroughputCalculator>();
    private HashMap<String,ThroughputCalculator> rxMap = new HashMap<String,ThroughputCalculator>();

    @Override
    public String getName() {
        return "Network";
    }

    @Override
    public String html() {
        try {
            return FileUtil.getContent(FileUtil.findURL("wa/server/plugin/hwstatus/NetStatus.tmpl"));
        } catch (IOException e) {
            return e.getMessage();
        }
    }

    @Override
    public void jsonUpdate(Map<String, String> request, DataNode root) {
        try{
            Sigar sigar = new Shell().getSigar();

            if(request.containsKey("net")){
                DataNode intfListNode = new DataNode(DataNode.DataType.List);
                String[] intfNameList = sigar.getNetInterfaceList();
                for( String intfName : intfNameList ){
                    DataNode intfNode = new DataNode(DataNode.DataType.Map);
                    if(idMap.containsKey(intfName))
                        intfNode.set("id", idMap.get(intfName));
                    else{
                        idMap.put(intfName, nextId);
                        intfNode.set("id", nextId++);
                    }

                    NetInterfaceStat net_stat = sigar.getNetInterfaceStat(intfName);
                    intfNode.set("name", intfName);
                    intfNode.set("speed", net_stat.getSpeed());
                    intfNode.set("dropped", net_stat.getRxDropped() + net_stat.getTxDropped() );
                    intfNode.set("error", net_stat.getRxErrors() + net_stat.getTxErrors() );
                    intfNode.set("total_tx", net_stat.getTxBytes());
                    intfNode.set("total_rx", net_stat.getRxBytes());

                    ThroughputCalculator txThroughput = txMap.get(intfName);
                    if(txThroughput == null) {
                        txThroughput = new ThroughputCalculator();
                        txMap.put(intfName, txThroughput);
                    }
                    txThroughput.setTotalHandledData(net_stat.getTxBytes());
                    intfNode.set("tx", txThroughput.getBitThroughput());

                    ThroughputCalculator rxThroughput = rxMap.get(intfName);
                    if(rxThroughput == null) {
                        rxThroughput = new ThroughputCalculator();
                        rxMap.put(intfName, rxThroughput);
                    }
                    rxThroughput.setTotalHandledData(net_stat.getRxBytes());
                    intfNode.set("rx", rxThroughput.getBitThroughput());

                    NetInterfaceConfig net_conf = sigar.getNetInterfaceConfig( intfName );
                    intfNode.set("up", (net_conf.getFlags() & NetFlags.IFF_UP) > 0 );
                    intfNode.set("ip", net_conf.getAddress() );
                    intfNode.set("netmask", net_conf.getNetmask() );
                    intfNode.set("mac", net_conf.getHwaddr() );
                    intfNode.set("type", net_conf.getType() );
                    intfNode.set("flags", NetFlags.getIfFlagsString(net_conf.getFlags()) );
                    intfNode.set("desc", net_conf.getDescription() );

                    intfListNode.add(intfNode);
                }
                root.set("net", intfListNode);
            }
            if(request.containsKey("routing")) {
                DataNode routeListNode = new DataNode(DataNode.DataType.List);
                NetRoute[] routes = sigar.getNetRouteList();
                for( NetRoute route : routes ) {
                    DataNode routeNode = new DataNode(DataNode.DataType.Map);
                    routeNode.set("interface", route.getIfname());
                    routeNode.set("destination", route.getDestination());
                    routeNode.set("gateway", route.getGateway());
                    routeNode.set("netmask", route.getMask());
                    routeNode.set("flags", NetFlags.getIfFlagsString((route.getFlags())));
                    routeNode.set("metric", route.getMetric());
                    routeListNode.add(routeNode);
                }
                root.set("routing", routeListNode);
            }
        } catch (SigarException e) {
            e.printStackTrace();
        }
    }


}
