<?php

namespace Tobuli\Reports;

use Carbon\Carbon;
use Formatter;
use Tobuli\Entities\Device;
use Tobuli\Entities\User;

class ReportManager
{
    public static $types = [
        1  => Reports\GeneralInformationReport::class,
        2  => Reports\GeneralInformationMergedReport::class,
        16 => Reports\GeneralInformationMergedCustomReport::class,
        42 => Reports\GeneralInformationMergedCustom2Report::class,
        49 => Reports\GeneralInformationMergedCustom3Report::class,
        3  => Reports\DrivesStopsReport::class,
        18 => Reports\DrivesStopsGeofencesReport::class,
        19 => Reports\DrivesStopsDriversReport::class,
        21 => Reports\DrivesStopsDriversBusinessReport::class,
        22 => Reports\DrivesStopsDriversPrivateReport::class,
        41 => Reports\DrivesStopsReportSimplified::class,
        40 => Reports\StopsReport::class,
        4  => Reports\TravelSheetReport::class,
        39 => Reports\TravelSheetReportCustom::class,
        5  => Reports\OverspeedsReport::class,
        47 => Reports\OverspeedsInGeofenceReport::class,
        6  => Reports\UnderspeedsReport::class,
        7  => Reports\GeofencesInOutReport::class,
        15 => Reports\GeofencesInOut24ModeReport::class,
        20 => Reports\GeofencesInOutEngineReport::class,
        28 => Reports\GeofencesShiftReport::class,
        31 => Reports\GeofencesTouchAllReport::class,
        44 => Reports\GeofencesTouchAllReport2::class,
        8  => Reports\EventDeviceReport::class,
        10 => Reports\FuelLevelReport::class,
        11 => Reports\FuelFillingsReport::class,
        //12 => FuelTheftsReport::class,
        13 => Reports\TemperatureReport::class,
        14 => Reports\RagReport::class,
        23 => Reports\RagSeatbeltReport::class,
        25 => Reports\ObjectHistoryReport::class,
        29 => Reports\EngineHoursVirtualReport::class,
        30 => Reports\IgnitionOnOff24ModeReport::class,
        32 => Reports\SentCommandsReport::class,
        33 => Reports\OverspeedCustomReport::class,
        34 => Reports\OverspeedCustomSummaryReport::class,
        35 => Reports\InstallationDeviceAllReport::class,
        36 => Reports\InstallationDeviceOfflineReport::class,
//        '37' => trans('front.loading_unloading'),
        38 => Reports\OfflineDeviceReport::class,
        43 => Reports\RoutesReport::class,
//        '24' => 'Birla ' . trans('global.custom'),
//        '27' => 'Automon ' . trans('global.custom'),
        46 => Reports\DeviceExpensesReport::class,
        45 => Reports\SpeedReport::class,
        48 => Reports\WorkHoursDailyReport::class,
        50 => Reports\ChecklistReport::class,
        51 => Reports\SpeedCompareGpsEcmReport::class,
        52 => Reports\OverspeedsSpeedECMReport::class,
    ];

    public static function getMetaList(User $user)
    {
        $list = [
            'device.sim_number' => trans('validation.attributes.sim_number'),
            'device.imei' => trans('validation.attributes.imei'),
            //'device.protocol' => trans('validation.attributes.protocol'),
            'device.device_model' => trans('front.model'),
            'device.object_owner' => trans('validation.attributes.object_owner'),
            'device.plate_number' => trans('validation.attributes.plate_number'),
            'device.registration_number' => trans('validation.attributes.registration_number'),
            'device.expiration_date' => trans('validation.attributes.expiration_date'),
            'device.vin' => trans('validation.attributes.vin'),
        ];

        return array_filter($list, function($stat, $key) use ($user){
            list($model,$attribute) = explode('.', $key);

            return $user->can('view', new Device(), $attribute);
        }, ARRAY_FILTER_USE_BOTH);
    }

    public static function getTitle($type)
    {
        return self::$types[$type]::title();
    }

    public function getList()
    {
        $list = [];

        foreach (self::$types as $type_id => $class)
        {
            if ( ! $class::isEnabled())
                continue;

            $list[$type_id] = $class::title();
        }

        return $list;
    }

    /**
     * @param $type
     * @return DeviceReport
     */
    public function report($type)
    {
        $class = self::$types[$type];

        return new $class();
    }

    public function fromRequest($data)
    {
        //check report
        $report = $this->report($data['type']);

        $user = auth()->user();
        Formatter::byUser($user);

        $data['date_from'] = Formatter::time()->reverse($data['date_from']);
        $data['date_to'] = Formatter::time()->reverse($data['date_to']);
        $data['user'] = $user;

        if ( ! empty($data['devices']))
            $data['devices'] = $user->devices()->with('sensors')->whereIn('id', $data['devices'])->get();

        if ( ! empty($data['geofences']))
            $data['geofences'] = $user->geofences()->whereIn('id', $data['geofences'])->get();

        return $this->from($data);
    }

    /**
     * @param \Tobuli\Entities\Report $report
     * @param $data
     * @return DeviceReport
     */
    public function fromEntity(\Tobuli\Entities\Report $report, $data)
    {
        //check report
        $this->report($data['type']);

        Formatter::byUser($data['user']);

        $data = array_merge($data, $report->toArray());

        $data['date_from'] = Formatter::time()->reverse($data['date_from']);
        $data['date_to'] = Formatter::time()->reverse($data['date_to']);

        $data['devices'] = $report->devices->filter(function ($device){
            return ! $device->isExpired();
        });
        $data['geofences'] = $report->geofences;

        return $this->from($data);
    }

    public function from($data)
    {
        $report = $this->report($data['type']);
        $report->setUser($data['user']);
        $report->setFormat($data['format']);
        $report->setRange($data['date_from'], $data['date_to']);

        if ( ! empty($data['metas']))
            $report->setMetas($data['metas']);
        if ( ! empty($data['devices']))
            $report->setDevices($data['devices']);
        if ( ! empty($data['geofences']))
            $report->setGeofences($data['geofences']);
        if ( ! empty($data['parameters']))
            $report->setParameters($data['parameters']);
        if ( ! empty($data['speed_limit']))
            $report->setSpeedLimit(Formatter::speed()->reverse($data['speed_limit']));
        if ( ! empty($data['stops']))
            $report->setStopMinutes($data['stops']);
        if ( ! empty($data['show_addresses']))
            $report->setShowAddresses(true);
        if ( ! empty($data['zones_instead']))
            $report->setZonesInstead(true);

        return $report;
    }

    public function debug($data = [])
    {
        $data = array_merge([
            'user' => auth()->user(),
            'format' => 'html',
            'date_from' => Carbon::now()->subDay()->format('Y-m-d H:i:s'),
            'date_to'   => Carbon::now()->format('Y-m-d H:i:s'),
            'geofences' => auth()->user()->geofences,
            'devices'   => \Tobuli\Entities\Device::with('sensors')->where('name', 'like', '%Demo%')->limit(5)->get(),
            'speed_limit' => 60,
            //'zones_instead' => true,
        ], $data);

        foreach ($this::$types as $type => $class) {
            $data['type'] = $type;

            try {
                $report = $this->from($data);
                echo $report->view();
            } catch (\Exception $e) {
                var_dump(array_except($data, ['user', 'devices', 'geofences']));
                throw $e;
            }
        }
    }
}