<?php

namespace App\Helpers;

use Carbon\Carbon;

class ChartHandler
{
    static function goliathDropped($_chh, $_asns, $_prefixes, $_include_bps = true, $_include_pps = true, $_period = 300) {

        $end = Carbon::now()->timestamp;
        $start = Carbon::now()->subSeconds($_period)->timestamp;

        $all_pps_event = $all_bps_event = [
            'data' => [],
            'categories' => [],
            'now' => $end,
            'start' => $start,
            'end' => $end
        ];

        $interval_second = $_period <= 60 ? 15 : ($_period > 21600 ? 30 : 15);
        $interval_divisor = $_period <= 60 ? 15 : ($_period > 21600 ? 30 : 15);

        foreach($_asns as $asn) {

            // Select flow information for that organisation
            $flow_query = null;

            if($_include_bps && $_include_pps) {
                $flow_query = $_chh->selectUnpaged("SELECT
                    TimeReceived,
                    ROUND(IF((DGbps IS NULL OR DGbps < 100) AND (DMpps IS NULL OR DMpps < 100000), 0, DGbps), 2) AS DroppedGbps,
                    IF((DGbps IS NULL OR DGbps < 100) AND (DMpps IS NULL OR DMpps < 100000), 0, DMpps) AS DroppedMpps,
                    now() AS CurrentTime,
                    now() - INTERVAL {p0:integer} SECOND AS StartTime
                    FROM (
                        SELECT
                            toStartOfInterval(TimeReceived, INTERVAL $interval_second SECOND) AS TimeReceived,
                            (SUM(CASE WHEN OutIfConnectivity = 'gol' THEN ((((Bytes * SamplingRate) * 8))) / 1000 / 1000 / $interval_divisor ELSE 0 END) -
                            SUM(CASE WHEN InIfConnectivity = 'gol' THEN ((((Bytes * SamplingRate) * 8))) / 1000 / 1000 / $interval_divisor ELSE 0 END)) AS DGbps,
                            (SUM(CASE WHEN OutIfConnectivity = 'gol' THEN ((Packets * SamplingRate)) / $interval_divisor  ELSE 0 END) -
                            SUM(CASE WHEN InIfConnectivity = 'gol' THEN ((Packets * SamplingRate)) / $interval_divisor ELSE 0 END)) AS DMpps
                        FROM flows
                        WHERE TimeReceived > now() - INTERVAL {p0:integer} SECOND
                            AND (OutIfConnectivity = 'gol' OR InIfConnectivity = 'gol')
                            AND DstNetTenant = 'as$asn'
                        GROUP BY
                            TimeReceived
                        ORDER BY TimeReceived ASC WITH FILL FROM toStartOfMinute(now() - INTERVAL {p0:integer} SECOND) TO toStartOfMinute(now()) STEP toIntervalSecond($interval_second)
                )", [ $_period ]);
            }  
            else if($_include_pps) {
                $flow_query = $_chh->selectUnpaged("SELECT
                    TimeReceived,
                    IF((DroppedGbps IS NULL OR DroppedGbps < 100) AND (DroppedMpps IS NULL OR DroppedMpps < 100000), 0, DroppedMpps) AS DroppedMpps,
                    now() AS CurrentTime,
                    now() - INTERVAL {p0:integer} SECOND AS StartTime
                    FROM (
                        SELECT
                            toStartOfInterval(TimeReceived, INTERVAL $interval_second SECOND) AS TimeReceived,
                            (SUM(CASE WHEN OutIfConnectivity = 'gol' THEN ((((Bytes * SamplingRate) * 8))) / 1000 / 1000 / $interval_divisor ELSE 0 END) -
                            SUM(CASE WHEN InIfConnectivity = 'gol' THEN ((((Bytes * SamplingRate) * 8))) / 1000 / 1000 / $interval_divisor ELSE 0 END)) AS DroppedGbps,
                            (SUM(CASE WHEN OutIfConnectivity = 'gol' THEN ((Packets * SamplingRate)) / $interval_divisor  ELSE 0 END) -
                            SUM(CASE WHEN InIfConnectivity = 'gol' THEN ((Packets * SamplingRate)) / $interval_divisor ELSE 0 END)) AS DroppedMpps
                        FROM flows
                        WHERE TimeReceived > now() - INTERVAL {p0:integer} SECOND
                            AND (OutIfConnectivity = 'gol' OR InIfConnectivity = 'gol')
                            AND DstNetTenant = 'as$asn'
                        GROUP BY
                            TimeReceived
                        ORDER BY TimeReceived ASC WITH FILL FROM toStartOfMinute(now() - INTERVAL {p0:integer} SECOND) TO toStartOfMinute(now()) STEP toIntervalSecond($interval_second)
                    )", [ $_period ]);
            }
            else if($_include_bps) {
                $flow_query = $_chh->selectUnpaged("SELECT
                    TimeReceived,
                    ROUND(IF((DroppedGbps IS NULL OR DroppedGbps < 100) AND (DroppedMpps IS NULL OR DroppedMpps < 100000), 0, DroppedGbps), 2) AS DroppedGbps,
                    now() AS CurrentTime,
                    now() - INTERVAL {p0:integer} SECOND AS StartTime
                    FROM (
                        SELECT
                            toStartOfInterval(TimeReceived, INTERVAL $interval_second SECOND) AS TimeReceived,
                            (SUM(CASE WHEN OutIfConnectivity = 'gol' THEN ((((Bytes * SamplingRate) * 8))) / 1000 / 1000 / $interval_divisor ELSE 0 END) -
                            SUM(CASE WHEN InIfConnectivity = 'gol' THEN ((((Bytes * SamplingRate) * 8))) / 1000 / 1000 / $interval_divisor ELSE 0 END)) AS DroppedGbps,
                            (SUM(CASE WHEN OutIfConnectivity = 'gol' THEN ((Packets * SamplingRate)) / $interval_divisor  ELSE 0 END) -
                            SUM(CASE WHEN InIfConnectivity = 'gol' THEN ((Packets * SamplingRate)) / $interval_divisor ELSE 0 END)) AS DroppedMpps
                        FROM flows
                        WHERE TimeReceived > now() - INTERVAL {p0:integer} SECOND
                            AND (OutIfConnectivity = 'gol' OR InIfConnectivity = 'gol')
                            AND DstNetTenant = 'as$asn'
                        GROUP BY
                            TimeReceived
                        ORDER BY TimeReceived ASC WITH FILL FROM toStartOfMinute(now() - INTERVAL {p0:integer} SECOND) TO toStartOfMinute(now()) STEP toIntervalSecond($interval_second)
                    )", [ $_period ]);
            }

            $flow_information = $flow_query->get();

            if($flow_information === null) {
                return [ $all_pps_event, $all_bps_event ];
            }

            // Do something with each individual flow...
            foreach($flow_information['data'] as $flow) {
                $start = Carbon::parse($flow['StartTime'])->timestamp;
                $now = Carbon::parse($flow['CurrentTime'])->timestamp;
                $at = Carbon::parse($flow['TimeReceived'])->timestamp;

                if($_include_pps) {
                    if(isset($all_pps_event['data'][$at])) {
                        $all_pps_event['data'][$at]['points'][] = [
                            'category' => "AS$asn",
                            'value' => $flow['DroppedMpps'] > 0 ? intval(floor($flow['DroppedMpps'])) : 0
                        ];
                    }
                    else {
                        $all_pps_event['data'][$at] = [
                            'key' => $flow['TimeReceived'],
                            'points' => [
                                [
                                    'category' => "AS$asn",
                                    'value' => $flow['DroppedMpps'] > 0 ? intval(floor($flow['DroppedMpps'])) : 0 
                                ]
                            ]
                        ];
                    }
                    
                    if($at > $all_pps_event['end']) {
                        $all_pps_event['end'] = $at;
                    }

                    if($all_pps_event['start'] != $start) {
                        $all_pps_event['start'] = $start;
                    }                    

                    if($all_pps_event['now'] != $now) {
                        $all_pps_event['now'] = $now;
                    }
                }
                
                if($_include_bps) {                    
                    if(isset($all_bps_event['data'][$at])) {
                        $all_bps_event['data'][$at]['points'][] = [
                            'category' => "AS$asn",
                            'value' => $flow['DroppedGbps'] > 0 ? round($flow['DroppedGbps'], 2) : 0 
                        ];
                    }
                    else {
                        $all_bps_event['data'][$at] = [
                            'key' => $flow['TimeReceived'],
                            'points' => [
                                [
                                    'category' => "AS$asn",
                                    'value' => $flow['DroppedGbps'] > 0 ? round($flow['DroppedGbps'], 2) : 0 
                                ]
                            ]
                        ];
                    }

                    if($at > $all_bps_event['end']) {
                        $all_bps_event['end'] = $at;
                    }

                    if($all_bps_event['start'] != $start) {
                        $all_bps_event['start'] = $start;
                    }                    

                    if($all_bps_event['now'] != $now) {
                        $all_bps_event['now'] = $now;
                    }
                }
            }

            // Store each ASN as a category
            $all_pps_event['categories'][] = ['name' => "AS$asn"];
            $all_bps_event['categories'][] = ['name' => "AS$asn"];
        }

        return [ $all_pps_event, $all_bps_event ];
    }
}
?>