/*
 * Copyright 2018-present Open Networking Foundation
 *
 * 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 org.onosproject.incubator.net.dpi.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.dpi.DpiStatInfo;
import org.onosproject.incubator.net.dpi.DpiStatistics;
import org.onosproject.incubator.net.dpi.DpiStatisticsManagerService;
import org.onosproject.incubator.net.dpi.FlowStatInfo;
import org.onosproject.incubator.net.dpi.ProtocolStatInfo;
import org.onosproject.incubator.net.dpi.TrafficStatInfo;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static java.lang.Thread.sleep;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * DPI Statistics Manager.
 */
@Component(immediate = true, service = DpiStatisticsManagerService.class)
public class DpiStatisticsManager implements DpiStatisticsManagerService {

    private ServerSocket serverSocket;
    private static int port = 11990; // socket server listening port

    private final Logger log = getLogger(getClass());

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected CoreService coreService;

    private ApplicationId appId;

    private final ExecutorService dpiListenerThread =
            Executors.newSingleThreadExecutor(groupedThreads("onos/apps/dpi", "dpi-listener"));

    DpiStatisticsListener dpiStatisticsListener = null;

    // 31*2(month)*24(hour)*3600(second)/5(second)
    private static final int MAX_DPI_STATISTICS_ENTRY = 1071360;

    private SortedMap<String, DpiStatistics> dpiStatisticsMap =
            new TreeMap<>(new MapComparator());

    private long convertTimeToLong(String timeString) {
        long timeLong = 0;

        try {
            // Time format: yyyy-MM-dd HH:mm:ss, Time Zone: GMT
            SimpleDateFormat df = new SimpleDateFormat(DATE_FMT, Locale.KOREA);
            df.setTimeZone(TimeZone.getTimeZone(TIME_ZONE));

             timeLong = df.parse(timeString).getTime();
        } catch (ParseException e) {
            log.error("Time parse error! Exception={}", e.toString());
        }

        return timeLong;
    }

    private static final String DATE_FMT = "yyyy-MM-dd HH:mm:ss";
    private static final String TIME_ZONE = "GMT";

    public static final int MAX_DPI_STATISTICS_REQUEST = 100;
    public static final int MAX_DPI_STATISTICS_TOPN = 100;

    @Activate
    public void activate(ComponentContext context) {
        appId = coreService.registerApplication("org.onosproject.dpi");

//        registerCodec(DpiStatistics.class, new DpiStatisticsCodec());
//        registerCodec(DpiStatInfo.class, new DpiStatInfoCodec());
//        registerCodec(TrafficStatInfo.class, new TrafficStatInfoCodec());
//        registerCodec(ProtocolStatInfo.class, new ProtocolStatInfoCodec());
//        registerCodec(FlowStatInfo.class, new FlowStatInfoCodec());

        dpiStatisticsListener = new DpiStatisticsListener();
        dpiListenerThread.execute(dpiStatisticsListener);

        log.info("Started", appId.id());
    }

    @Deactivate
    public void deactivate() {
        log.info("Deactivated...");
        dpiListenerThread.shutdownNow();
        log.info("Stopped");
    }

    @Override
    public DpiStatistics getDpiStatisticsLatest() {
        if (dpiStatisticsMap.size() > 0) {
            return dpiStatisticsMap.get(dpiStatisticsMap.firstKey());
        } else {
            return null;
        }
    }

    @Override
    public DpiStatistics getDpiStatisticsLatest(int topnProtocols, int topnFlows) {
        DpiStatistics ds, topnDs;

        ds = getDpiStatisticsLatest();
        topnDs = processTopn(ds, topnProtocols, topnFlows);

        return topnDs;
    }

    @Override
    public List<DpiStatistics> getDpiStatistics(int lastN) {
        List<DpiStatistics> dsList = new ArrayList<>();
        DpiStatistics ds;

        if (lastN > MAX_DPI_STATISTICS_REQUEST) {
            lastN = MAX_DPI_STATISTICS_REQUEST;
        }

        SortedMap tempMap = new TreeMap(new MapComparator());
        tempMap.putAll(dpiStatisticsMap);

        for (int i = 0; i < lastN && i < tempMap.size(); i++) {
            ds = (DpiStatistics) tempMap.get(tempMap.firstKey());
            dsList.add(i, new DpiStatistics(ds.receivedTime(), ds.dpiStatInfo()));

            tempMap.remove(tempMap.firstKey());
        }

        return dsList;
    }

    @Override
    public List<DpiStatistics> getDpiStatistics(int lastN, int topnProtocols, int topnFlows) {
        List<DpiStatistics> dsList;
        List<DpiStatistics> topnDsList = new ArrayList<>();
        DpiStatistics ds, topnDs;

        dsList = getDpiStatistics(lastN);
        for (int i = 0; i < dsList.size(); i++) {
            ds = dsList.get(i);
            topnDs = processTopn(ds, topnProtocols, topnFlows);
            topnDsList.add(i, topnDs);
        }

        return topnDsList;
    }

    @Override
    public DpiStatistics getDpiStatistics(String receivedTime) {
        DpiStatistics ds;

        if (receivedTime == null) {
            return null;
        }

        if (!dpiStatisticsMap.containsKey(receivedTime)) {
            return null;
        }

        ds = dpiStatisticsMap.get(receivedTime);

        return ds;
    }

    @Override
    public DpiStatistics getDpiStatistics(String receivedTime, int topnProtocols, int topnFlows) {
        DpiStatistics ds, topnDs;

        ds = getDpiStatistics(receivedTime);

        topnDs = processTopn(ds, topnProtocols, topnFlows);

        return topnDs;
    }

    @Override
    public DpiStatistics addDpiStatistics(DpiStatistics ds) {
        if (ds == null) {
            return ds;
        }

        // check the time. The firstKey is lastTime because of descending sorted order
        if (dpiStatisticsMap.size() > 0) {
            String lastTime = dpiStatisticsMap.get(dpiStatisticsMap.firstKey()).receivedTime();
            String inputTime = ds.receivedTime();

            long lastTimeLong = convertTimeToLong(lastTime);
            long inputTimeLong = convertTimeToLong(inputTime);

            if (lastTimeLong >= inputTimeLong) {
                return null;
            }
        }

        if (dpiStatisticsMap.size() >= MAX_DPI_STATISTICS_ENTRY) {
            // remove the last (oldest) entry
            dpiStatisticsMap.remove(dpiStatisticsMap.lastKey());
        }

        if (dpiStatisticsMap.containsKey(ds.receivedTime())) {
            log.warn("addDpiStatistics(), {} dpiStatistics is already existing!",
                      ds.receivedTime());
            return null;
        }

        dpiStatisticsMap.put(ds.receivedTime(), ds);
        log.debug("addDpiStatistics: dpiResultJson data[time={}] is added " +
                          "into DpiStatisticsMap size={}.",
                  ds.receivedTime(), dpiStatisticsMap.size());

        return ds;
    }

    private class MapComparator implements Comparator<String> {
        @Override
        public int compare(String rt1, String rt2) {
            long rt1Long = convertTimeToLong(rt1);
            long rt2Long = convertTimeToLong(rt2);

            // Descending order
            if (rt1Long > rt2Long) {
                return -1;
            } else if (rt1Long < rt2Long) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    private class ProtocolComparator implements Comparator<ProtocolStatInfo> {
        @Override
        public int compare(ProtocolStatInfo p1, ProtocolStatInfo p2) {
            //Descending order
            if (p1.bytes() > p2.bytes()) {
                return -1;
            } else if (p1.bytes() < p2.bytes()) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    private class FlowComparator implements Comparator<FlowStatInfo> {
        @Override
        public int compare(FlowStatInfo f1, FlowStatInfo f2) {
            // Descending order
            if (f1.bytes() > f2.bytes()) {
                return -1;
            } else if (f1.bytes() < f2.bytes()) {
                return 1;
            } else {
                return 0;
            }
        }
    }
    private DpiStatistics processTopn(DpiStatistics ds, int topnProtocols, int topnFlows) {
        if (ds == null) {
            return null;
        }

        if (topnProtocols <= 0) {
            // displays all entries
            topnProtocols = 0;
        } else if (topnProtocols > MAX_DPI_STATISTICS_TOPN) {
            topnProtocols = MAX_DPI_STATISTICS_TOPN;
        }

        if (topnFlows <= 0) {
            // displays all entries
            topnFlows = 0;
        } else if (topnFlows > MAX_DPI_STATISTICS_TOPN) {
            topnFlows = MAX_DPI_STATISTICS_TOPN;
        }

        if (topnProtocols == 0 && topnFlows == 0) {
            return ds;
        }

        TrafficStatInfo tsi = ds.dpiStatInfo().trafficStatistics();
        List<ProtocolStatInfo> psiList;
        List<FlowStatInfo> kfList;
        List<FlowStatInfo> ufList;

        List<ProtocolStatInfo> pList = ds.dpiStatInfo().detectedProtos();
        Collections.sort(pList, new ProtocolComparator());
        if (topnProtocols > 0 && topnProtocols < pList.size()) {
            psiList = pList.subList(0, topnProtocols);
        } else {
            psiList = pList;
        }


        List<FlowStatInfo> fList = ds.dpiStatInfo().knownFlows();
        Collections.sort(fList, new FlowComparator());
        if (topnFlows > 0 && topnFlows < fList.size()) {
            kfList = fList.subList(0, topnFlows);
        } else {
            kfList = fList;
        }

        fList = ds.dpiStatInfo().unknownFlows();
        Collections.sort(fList, new FlowComparator());
        if (topnFlows > 0 && topnFlows < fList.size()) {
            ufList = fList.subList(0, topnFlows);
        } else {
            ufList = fList;
        }

        DpiStatInfo dsi = new DpiStatInfo();
        dsi.setTrafficStatistics(tsi);
        dsi.setDetectedProtos(psiList);
        dsi.setKnownFlows(kfList);
        dsi.setUnknownFlows(ufList);

        DpiStatistics retDs = new DpiStatistics(ds.receivedTime(), dsi);
        return retDs;
    }

    /**
     * Receiving DPI Statistics result thread.
     */
    private class DpiStatisticsListener implements Runnable {
        Socket clientSocket = null;
        BufferedReader in = null;
        PrintWriter out = null;

        String resultJsonString = null;

        static final int MAX_SLEEP_COUNT = 10;
        int sleepCount = 0;

        @Override
        public void run() {
            log.info("DpiStatisticsListener: Receiving thread started...");
            receiveDpiResult();
        }

        private void receiveDpiResult() {
            try {
                serverSocket = new ServerSocket(port);
            } catch (Exception e) {
                log.error("DpiStatisticsListener: ServerSocket listening error from port={} in localhost, exception={}",
                          port, e.toString());
                return;
            }

            try {
                while (!Thread.currentThread().isInterrupted()) {
                    if (clientSocket == null) {
                        log.info("DpiStatisticsListener: Waiting for accepting from dpi client...");
                        clientSocket = serverSocket.accept();
                        log.info("DpiStatisticsListener: Accepted from dpi client={}",
                                 clientSocket.getRemoteSocketAddress().toString());

                        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                        out = new PrintWriter(clientSocket.getOutputStream(), true); // For disconnecting check!

                        resultJsonString = null;
                    }

                    sleepCount = 0;
                    while (!in.ready()) {
                        sleep(1000); // sleep one second.
                        if (out.checkError() || ++sleepCount >= MAX_SLEEP_COUNT) {
                            log.debug("DpiStatisticsListener: server and socket connect is lost...");
                            in.close();
                            in = null;
                            out.close();
                            out = null;
                            clientSocket.close();
                            clientSocket = null;

                            break;
                        }
                    }

                    if (in != null) {
                        resultJsonString = in.readLine();

                        // process the result
                        log.trace("DpiStatisticsListener: resultJsonString={}", resultJsonString);
                        processResultJson(resultJsonString);
                    }
                }
            } catch (Exception e) {
                log.error("DpiStatisticsListener: Exception = {}", e.toString());
                return;
            } finally {
                try {
                    if (serverSocket != null) {
                        if (clientSocket != null) {
                            if (in != null) {
                                in.close();
                            }
                            if (out != null) {
                                out.close();
                            }
                            clientSocket.close();
                            //log.debug("DpiResultListener: stop(): Socket close() is done...");
                        }
                        serverSocket.close();
                        //log.debug("DpiResultListener: stop(): Server close() is done...");
                    }
                } catch (Exception e) {
                    log.error("DpiStatisticsListener: stop(): Server Socket closing error, exception={}",
                            e.toString());
                }
            }
        }

        private void processResultJson(String resultJsonString) {
            Date tr = new Date(System.currentTimeMillis());
            SimpleDateFormat df = new SimpleDateFormat(DATE_FMT, Locale.KOREA);
            df.setTimeZone(TimeZone.getTimeZone(TIME_ZONE));

            String curReceivedTime = new String(df.format(tr));
            String curResultJson = new String(resultJsonString);

            DpiStatInfo dpiStatInfo;
            ObjectMapper mapper = new ObjectMapper();
            try {
                dpiStatInfo = mapper.readValue(curResultJson, DpiStatInfo.class);
            } catch (IOException e) {
                log.error("DpiStatisticsListener: ObjectMapper Exception = {}", e.toString());
                return;
            }

            DpiStatistics dpiStatistics = new DpiStatistics(curReceivedTime, dpiStatInfo);

            addDpiStatistics(dpiStatistics);
        }
    }
}
