<?php

class ReportController extends Controller {

    public function actionCreate() {
        if (!isset($_REQUEST ['workPeriodID']))
            throw new CHttpException(400, Yii::app('t', 'workPeriodID is required.'));

        $workPeriodID = (int) $_REQUEST ['workPeriodID'];

        $this->showReport($workPeriodID, false);
    }

    public function actionPreview() {
        if (!isset($_REQUEST ['workPeriodID']))
            throw new CHttpException(400, Yii::app('t', 'workPeriodID is required.'));

        $workPeriodID = (int) $_REQUEST ['workPeriodID'];

        $this->showReport($workPeriodID, true);
    }

    public function actionCreateByService() {
        if (!isset($_REQUEST ['serviceID']))
            throw new CHttpException(400, Yii::app('t', 'serviceID is required.'));
        $serviceID = (int) $_REQUEST ['serviceID'];

        $this->showReportByService($serviceID, false);
    }

    public function actionPreviewByService() {
        if (!isset($_REQUEST ['serviceID']))
            throw new CHttpException(400, Yii::app('t', 'serviceID is required.'));

        $serviceID = (int) $_REQUEST ['serviceID'];

        $this->showReportByService($serviceID, true);
    }

    /**
     *
     * @param integer $workPeriodID          
     * @param boolean $preview          
     */
    protected function showReport($workPeriodID, $preview) {

        if (!ExtCode::acquireAccess()) {
            $this->renderText("<b>Attenzione!</b><br><br> Un altro utente sta effetuando un report.<br>Si prega di attendere e riprovare in seguito.");
            return;
        }
 
        $period = $this->loadWorkPeriod($workPeriodID);

        $report = new Report (); // approved and invalid
        $report->initByWorkPeriod($period, false);

        if (!$preview) {
            $events = EventTagger::tag($report->repository->all);
        } else {
            $events = array_convert($report->repository->all, function (Event $e) {
                $e->ext_code = $e->validation_result == 'approved' ? 'DEMO' : ExtCode::NULL_EXT_CODE;
                return $e;
            });
        }

       ExtCode::releaseAccess();
            
//    if ($period->report_generation_date == NULL)
        {
            $converterEventToId = function (Event $e) {
                return $e->ID;
            };

            $reportApproved = new Report (); // approved only
            $reportApproved->initByWorkPeriod($period, true);

            $eventsApproved = $reportApproved->repository->all;

            if (!$preview) {
                $period->report_generation_date = new DateTime ();
                $period->events_count = count($eventsApproved);
                $period->events_ids = implode(",", array_convert($eventsApproved, $converterEventToId));
                $period->activateRegistration();
                $period->save();
            }
        }

        //$this->registerAllExportCounters();

        $eventsByGateGroup = GroupEventsByGateGroup::run($events);

        // this will hold data we will pass to views for rendering
        $reportData = array(
            'user' => $period->user,
            'period' => $period,
            'generationTime' => DateHelper::formatDateTime($period->report_generation_date)
        );

        $reportPrinter = ReportPrinterFactory::getReportPrinter();

        foreach ($eventsByGateGroup as $aGroup) {

            $gateGroup = $aGroup['gateGroup'];
            $events = $aGroup['events'];
            $events = array_sort($events, function($a, $b) {
                $a = new DateTimeEx($a->StartTime);
                return $a->compare(new DateTimeEx($b->StartTime));
            });
            $totalEvents = count($events);
            $validEvents = array_filter($events, function($e) {
                return $e->ext_code != ExtCode::NULL_EXT_CODE;
            });
            $firstEvent = array_first($validEvents);
            $lastEvent = array_last($validEvents);
            $gates = $gateGroup->gates;

            // fill report data to render
            $reportData['counterOK'] = 0;
            $reportData['counterNO'] = 0;
            foreach ($events as $event) {
                if ($event->ext_code != ExtCode::NULL_EXT_CODE) {
                    $reportData['counterOK'] ++;
                } else {
                    $reportData['counterNO'] ++;
                }
            }
            $reportData['gateGroup'] = $aGroup['gateGroup'];
            //$reportData['events'] = $aGroup['events'];
            $reportData['events'] = $events;
            $reportData['totalEvents'] = count($events);
            $reportData['validEvents'] = $validEvents;
            $reportData['firstEvent'] = $firstEvent;
            $reportData['lastEvent'] = $lastEvent;
            $reportData['gates'] = $gateGroup->gates;

            // build a temporary ReportDocument to use,
            // we will persist it later if necessary
            $reportDocument = new ReportDocument();
            $reportDocument->UserID = $period->id_user;
            $reportDocument->PeriodID = $period->id;
            $reportDocument->serviceID = 0;
            $reportDocument->GroupID = $gateGroup->ID;
            $reportDocument->CreationTime = $period->report_generation_date;
            $reportDocument->MinExtcode = $firstEvent->ext_code;
            $reportDocument->MaxExtcode = $lastEvent->ext_code;
            $reportDocument->approved_events = $validEvents;

            // get the report title
            $title = $reportDocument->getTitle();

            // build the PDF report and store it in an
            // array we will pass to the view
            $pdfs[$reportData['gateGroup']->name] = $reportPrinter->printReport($title, $reportData);
            if (!$preview) {

                // set the PDF content
                $reportDocument->Document = end($pdfs);

                // persist document on DB
                $res = $reportDocument->save();
            }
        }

        if (!$preview && !$period->closed) {

            // force user logout
            Yii::app()->user->logout();

            // redirect to login page
            $this->redirect(array("session/login/"));
        } else if (!$preview) {

            // redirect to report archive view
            $this->redirect(array("reportArchive/index/"));
        } else {

            // render report preview page
            $this->render('sessionReportsPreviewViewer', array('pdfs' => $pdfs, 'workPeriod' => $period));
        }
    }

    /**
     *
     * @param integer $workPeriodID
     * @param boolean $preview
     */
    protected function showReportByService($serviceID, $preview) {
        if (!ExtCode::acquireAccess()) {
            $this->renderText("<b>Attenzione!</b><br><br> Un altro utente sta effetuando un report.<br>Si prega di attendere e riprovare in seguito.");
            return;
        }
        $service = $this->loadService($serviceID);

        $report = new Report (); // approved and invalid
        $report->initByService($service, false); // approved and invalid


        if (!$preview) {
            $events = EventTagger::tag($report->repository->all);
        } else {
            $events = array_convert($report->repository->all, function (Event $e) {
                $e->ext_code = $e->validation_result == 'approved' ? 'DEMO' : ExtCode::NULL_EXT_CODE;
                return $e;
            });
        }

        ExtCode::releaseAccess();
            
        //    if ($period->report_generation_date == NULL)
        {
            $converterEventToId = function (Event $e) {
                return $e->ID;
            };

            $reportApproved = new Report (); // approved only
            $reportApproved->initByService($service, true); // approved only

            $eventsApproved = $reportApproved->repository->all;

            if (!$preview) {
                $service->report_generation_date = new DateTime ();
                $service->report_user = $service->assignedOperator->id;
                $service->id_user_validating = 0;
                $service->activateRegistration();
                $service->save();
            }
        }

        //$this->registerAllExportCounters();

        $eventsByGateGroup = GroupEventsByGateGroup::run($events);


        // this will hold data we will pass to views for rendering
        $reportData = array(
            'user' => $service->assignedOperator,
            'period' => null,
            'generationTime' => DateHelper::formatDateTime($service->report_generation_date)
        );




        $reportPrinter = ReportPrinterFactory::getReportPrinter();


        foreach ($eventsByGateGroup as $aGroup) {


            $gateGroup = $aGroup['gateGroup'];
            $events = $aGroup['events'];
            $events = array_sort($events, function($a, $b) {
                $a = new DateTimeEx($a->StartTime);
                return $a->compare(new DateTimeEx($b->StartTime));
            });
            $totalEvents = count($events);
            $validEvents = array_filter($events, function($e) {
                return $e->ext_code != ExtCode::NULL_EXT_CODE;
            });
            $firstEvent = array_first($validEvents);
            $lastEvent = array_last($validEvents);
            $gates = $gateGroup->gates;

            // fill report data to render
            $reportData['counterOK'] = 0;
            $reportData['counterNO'] = 0;
            foreach ($events as $event) {
                if ($event->ext_code != ExtCode::NULL_EXT_CODE) {
                    $reportData['counterOK'] ++;
                } else {
                    $reportData['counterNO'] ++;
                }
            }
            $reportData['gateGroup'] = $aGroup['gateGroup'];
            //$reportData['events'] = $aGroup['events'];
            $reportData['events'] = $events;
            $reportData['totalEvents'] = count($events);
            $reportData['validEvents'] = $validEvents;
            $reportData['firstEvent'] = $firstEvent;
            $reportData['lastEvent'] = $lastEvent;
            $reportData['gates'] = $gateGroup->gates;

            // build a temporary ReportDocument to use,
            // we will persist it later if necessary
            $reportDocument = new ReportDocument();
            $reportDocument->UserID = $service->assignedOperator->id;
            $reportDocument->PeriodID = 0;
            $reportDocument->serviceID = $service->ID;
            $reportDocument->GroupID = $gateGroup->ID;
            $reportDocument->CreationTime = $service->report_generation_date;
            $reportDocument->MinExtcode = $firstEvent->ext_code;
            $reportDocument->MaxExtcode = $lastEvent->ext_code;
            $reportDocument->total_events = $totalEvents;
            $reportDocument->approved_events = $validEvents;
            $reportDocument->invalid_events = count($events) - count($validEvents);
            $reportDocument->uuid = getGUID();


            $eventReg = NULL;
            if (paramdeep('security', 'send_export_registration'))
                $eventReg = EventServerRegistration::model()->byMe()->find();

            if (!isEmpty($eventReg))
                $reportDocument->id_eventserver = $eventReg->id;
            else
                $reportDocument->id_eventserver = 0;


            // get the report title
            $title = $reportDocument->getTitle();




            // build the PDF report and store it in an
            // array we will pass to the view
            $pdfs[$reportData['gateGroup']->name] = $reportPrinter->printReport($title, $reportData);



            if (!$preview) {

                // set the PDF content
                $reportDocument->Document = end($pdfs);

                // persist document on DB
                if (!$reportDocument->save()) {

                    echo ($reportDocument->getErrors());
                }
            }
        }


        if (!$preview) {

            // redirect to report archive view
            $this->redirect(array("reportArchive/index/"));
        } else {

            // render report preview page
            $this->render('sessionReportsPreviewViewerByService', array('pdfs' => $pdfs, 'service' => $service));
        }
    }

    public function actionDoRegisterAllExportCounters() {
        $this->registerAllExportCounters();
    }

    public function actionConfirm($workPeriodID) {
        $checkExpDay = paramdeep('security', 'export_expiry_date_check');

        if (!isEmpty($checkExpDay) && $checkExpDay) {
            $EventServerReg = EventServerRegistration::model()->byMe()->find();

            if (isEmpty($EventServerReg)) {
                $this->renderPartial('_licenseConnectionFailed');
                return;
            }


            if (isEmpty($EventServerReg->export_expiry_date)) {
                $this->renderPartial('_licenseExpired');
                return;
            }
            $nowDate = DateTimeEx::now();

            if ($nowDate > $EventServerReg->export_expiry_date) {
                $this->renderPartial('_licenseExpired');
            }
        }

        // ensure work period really exists
        $workPeriod = $this->loadWorkPeriod($workPeriodID);

        $this->renderPartial('_confirm', array(
            'workPeriodID' => $workPeriod->id,
            'workPeriodClosed' => $workPeriod->closed
        ));
    }

    public function actionConfirmByService($serviceID) {
        $checkExpDay = paramdeep('security', 'export_expiry_date_check');

        if (!isEmpty($checkExpDay) && $checkExpDay) {
            $EventServerReg = EventServerRegistration::model()->byMe()->find();

            if (isEmpty($EventServerReg)) {
                $this->renderPartial('_licenseConnectionFailed');
                return;
            }


            if (isEmpty($EventServerReg->export_expiry_date)) {
                $this->renderPartial('_licenseExpired');
                return;
            }
            $nowDate = DateTimeEx::now();

            if ($nowDate > $EventServerReg->export_expiry_date) {
                $this->renderPartial('_licenseExpired');
            }
        }

        // ensure work period really exists
        $service = $this->loadService($serviceID);

        $this->renderPartial('_confirmByService', array(
            'serviceID' => $service->ID
        ));
    }

    public function actionViewSummary($workPeriodID) {
        $period = $this->loadWorkPeriod($workPeriodID);
        $report = new Report ( );
        $report->initByWorkPeriod($period);
        $this->renderPartial('/workPeriod/_summary', array(
            'workPeriodID' => $workPeriodID,
            'repository' => $report->repository
        ));
    }

    /**
     *
     * @param integer $id          
     * @throws CHttpException
     * @return WorkPeriod
     */
    public function loadWorkPeriod($id) {
        $period = WorkPeriod::model()->findByPk($id);
        if ($period === null)
            throw new CHttpException(404, Yii::t('app', 'The requested page does not exist.'));
        return $period;
    }

    /**
     *
     * @param integer $id
     * @throws CHttpException
     * @return Service
     */
    public function loadService($id) {
        $service = Service::model()->findByPk($id);
        if ($service === null)
            throw new CHttpException(404, Yii::t('app', 'The requested run does not exist.'));
        return $service;
    }

    public function registerAllExportCounters() {
        $sendExp = paramdeep('security', 'send_export_registration');
        if (isEmpty($sendExp) || $sendExp == false)
            return true;

        $workPeriods = WorkPeriod::model()->to_register()->findAll();
        foreach ($workPeriods as $wp) {
            $report = new Report (); // approved and invalid

            $report->initByWorkPeriod($wp, false);

            if ($this->registerExportCounters($report->repository->all, $wp->user, $wp->report_generation_date, $wp->id, 0)) {
                $wp->confirmRegistration();
                $wp->save();
            }
        }


        $services = Service::model()->to_register()->findAll();
        foreach ($services as $sw) {
            $report = new Report (); // approved and invalid
            $report->initByService($sw, false);

            if ($this->registerExportCounters($report->repository->all, $sw->registerOperator, $sw->report_generation_date, 0, $sw->ID)) {
                $sw->confirmRegistration();
                $sw->save();
            }
        }
    }

    public function registerExportCounters($events, $user, $ext_code_time, $id_work_period, $id_service) {
        set_time_limit(60);

        if (count($events) <= 0)
            return true;

        $gates = Gate::model()->findAll();

        foreach ($gates as $gate) {
            $gateConters[$gate->Gate]['description'] = $gate->Descrizione;
            $gateConters[$gate->Gate]['exported'] = 0;
            $gateConters[$gate->Gate]['gate_sn'] = $gate->Gate;
            $gateConters[$gate->Gate]['gate_type'] = $gate->GateType;
            $gateConters[$gate->Gate]['gate_model'] = $gate->device_model;
            $gateConters[$gate->Gate]['deleted'] = 0;
            $gateConters[$gate->Gate]['plate_changed'] = 0;
            $gateConters[$gate->Gate]['min_ext_code'] = 0;
            $gateConters[$gate->Gate]['max_ext_code'] = 0;
        }

        $gateConters[$event->Gate]['deleted'] = 0;
        $gateConters[$event->Gate]['plate_changed'] = 0;
        $gateConters[$event->Gate]['min_ext_code'] = 0;
        $gateConters[$event->Gate]['max_ext_code'] = 0;
        $gateConters[$event->Gate]['num_of_events'] = 0;

        foreach ($events as $event) {
            if ($event->ext_code != ExtCode::NULL_EXT_CODE) {
                $gateConters[$event->Gate]['exported'] += 1;

                if ($gateConters[$event->Gate]['min_ext_code'] === 0) {
                    $gateConters[$event->Gate]['min_ext_code'] = $event->ext_code;
                    $gateConters[$event->Gate]['max_ext_code'] = $event->ext_code;
                } else {
                    $gateConters[$event->Gate]['min_ext_code'] = min($event->ext_code, $gateConters[$event->Gate]['min_ext_code']);
                    $gateConters[$event->Gate]['max_ext_code'] = max($event->ext_code, $gateConters[$event->Gate]['max_ext_code']);
                }
            }

            if ($event->ext_code == ExtCode::NULL_EXT_CODE)
                $gateConters[$event->Gate]['deleted'] += 1;

            if (!isEmpty($event->ExtPlate) && $event->ExtPlate != $event->Plate)
                $gateConters[$event->Gate]['plate_changed'] += 1;

            $gateConters[$event->Gate]['num_of_events'] += 1;
        }



        $eventReg = EventServerRegistration::model()->byMe()->find();

        if (isEmpty($eventReg))
            return false;


        $resSave = true;

        foreach ($gateConters as $gateC) {
            if ($gateC['num_of_events'] > 0) {
                if ($id_work_period > 0)
                    $expExisting = ExportedEvents::model()->byServer($eventReg->id)->byGate($gateC['gate_sn'])->byWorkPeriod($id_work_period)->count();
                else
                    $expExisting = ExportedEvents::model()->byServer($eventReg->id)->byGate($gateC['gate_sn'])->byService($id_service)->count();

                if ($expExisting > 0) {
                    if ($id_work_period > 0)
                        $expEv = ExportedEvents::model()->byServer($eventReg->id)->byGate($gateC['gate_sn'])->byWorkPeriod($id_work_period)->find();
                    else
                        $expEv = ExportedEvents::model()->byServer($eventReg->id)->byGate($gateC['gate_sn'])->byService($id_service)->find();

                    $expEv->export_time = $ext_code_time;
                    $expEv->exported_events = $gateC['exported'];
                    $expEv->deleted_events = $gateC['deleted'];
                    $expEv->plate_changes = $gateC['plate_changed'];
                    $expEv->min_ext_code = $gateC['min_ext_code'];
                    $expEv->max_ext_code = $gateC['max_ext_code'];
                    $expEv->id_event_server = $eventReg->id;
                    $expEv->user_name = $user->first_name . " " . $user->last_name;
                    $expEv->gate_sn = $gateC['gate_sn'];
                    $expEv->gate_type = $gateC['gate_type'];
                    $expEv->gate_model = $gateC['gate_model'];
                    $expEv->gate_description = $gateC['description'];
                    $expEv->validated_events = $gateC['num_of_events'];
                    $expEv->id_work_period = $id_work_period;
                    $expEv->id_service = $id_service;
                    $expEv->id_report = $id_report;

                    if (!$expEv->save())
                        $resSave = false;
                }
                else {

                    $expEv = new ExportedEvents;

                    $expEv->export_time = $ext_code_time;
                    $expEv->exported_events = $gateC['exported'];
                    $expEv->deleted_events = $gateC['deleted'];
                    $expEv->plate_changes = $gateC['plate_changed'];
                    $expEv->min_ext_code = $gateC['min_ext_code'];
                    $expEv->max_ext_code = $gateC['max_ext_code'];
                    $expEv->id_event_server = $eventReg->id;
                    $expEv->user_name = $user->first_name . " " . $user->last_name;
                    $expEv->gate_sn = $gateC['gate_sn'];
                    $expEv->gate_type = $gateC['gate_type'];
                    $expEv->gate_model = $gateC['gate_model'];
                    $expEv->gate_description = $gateC['description'];
                    $expEv->validated_events = $gateC['num_of_events'];
                    $expEv->id_work_period = $id_work_period;
                    $expEv->id_service = $id_service;
                    $expEv->id_report = $id_report;

                    if (!$expEv->save())
                        $resSave = false;
                }
            }
        }

        return $resSave;
    }

}
