package FHEM::EaseeWallbox;

use strict;
use warnings;
use Data::Dumper;
use utf8;
use Encode qw( encode_utf8 );
use HttpUtils;

# try to use JSON::MaybeXS wrapper
#   for chance of better performance + open code
eval {
    require JSON::MaybeXS;
    import JSON::MaybeXS qw( decode_json encode_json );
    1;
} or do {

    # try to use JSON wrapper
    #   for chance of better performance
    eval {
        # JSON preference order
        local $ENV{PERL_JSON_BACKEND} =
          'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP'
          unless ( defined( $ENV{PERL_JSON_BACKEND} ) );

        require JSON;
        import JSON qw( decode_json encode_json );
        1;
    } or do {

        # In rare cases, Cpanel::JSON::XS may
        #   be installed but JSON|JSON::MaybeXS not ...
        eval {
            require Cpanel::JSON::XS;
            import Cpanel::JSON::XS qw(decode_json encode_json);
            1;
        } or do {

            # In rare cases, JSON::XS may
            #   be installed but JSON not ...
            eval {
                require JSON::XS;
                import JSON::XS qw(decode_json encode_json);
                1;
            } or do {

                # Fallback to built-in JSON which SHOULD
                #   be available since 5.014 ...
                eval {
                    require JSON::PP;
                    import JSON::PP qw(decode_json encode_json);
                    1;
                } or do {

                    # Fallback to JSON::backportPP in really rare cases
                    require JSON::backportPP;
                    import JSON::backportPP qw(decode_json encode_json);
                    1;
                };
            };
        };
    };
};

# Import von Funktionen und/oder Variablen aus der FHEM main
# man kann ::Funktionaname wählen und sich so den Import schenken. Variablen sollten aber
#   sauber importiert werden
use GPUtils qw(GP_Import);

## Import der FHEM Funktionen
#-- Run before package compilation
BEGIN {
    # Import from main context
    GP_Import(
        qw(
          readingFnAttributes
          )
    );
}

## Datapoint, all behind API URI
my %dpoints = (
    getOAuthToken             => 'accounts/login',
    getRefreshToken           => 'accounts/refresh_token',
    getProfile                => 'accounts/profile',
    getChargingSession        => 'chargers/#ChargerID#/sessions/ongoing',
    getChargers               => 'accounts/chargers',
    getProducts               => 'accounts/products?userId=#UserId#',
    getChargerSite            => 'chargers/#ChargerID#/site',
    getChargerDetails         => 'chargers/#ChargerID#/details',
    getChargerConfiguration   => 'chargers/#ChargerID#/config',
    getChargerSessionsMonthly => 'sessions/charger/#ChargerID#/monthly',
    getChargerSessionsDaily   => 'sessions/charger/#ChargerID#/daily',
    getChargerState           => 'chargers/#ChargerID#/state',
    getCurrentSession         => 'chargers/#ChargerID#/sessions/ongoing',
    setCableLockState         => 'chargers/#ChargerID#/commands/lock_state',
    setReboot                 => 'chargers/#ChargerID#/commands/reboot',
    setUpdateFirmware      => 'chargers/#ChargerID#/commands/update_firmware',
    setEnableSmartCharging => 'chargers/#ChargerID#/commands/smart_charging',
    setStartCharging       => 'chargers/#ChargerID#/commands/start_charging',
    setStopCharging        => 'chargers/#ChargerID#/commands/stop_charging',
    setPauseCharging       => 'chargers/#ChargerID#/commands/pause_charging',
    setResumeCharging      => 'chargers/#ChargerID#/commands/resume_charging',
    setToggleCharging      => 'chargers/#ChargerID#/commands/toggle_charging',
    setOverrideChargingSchedule =>
      'chargers/#ChargerID#/commands/override_schedule',
    setPairRFIDTag =>
      'chargers/#ChargerID#/commands/set_rfid_pairing_mode_async',
    changeChargerSettings => 'chargers/#ChargerID#/settings',
    setChargingPrice      => 'sites/#SiteID#/price',
);

#Private function to evaluate command-lists
# private funktionen beginnen immer mit _

#############################
sub getCmdList {

    return $retVal;
}

sub Initialize {
    my ($hash) = @_;

    $hash->{DefFn}   = \&Define;
    $hash->{UndefFn} = \&Undef;
    $hash->{SetFn}   = \&Set;
    $hash->{GetFn}   = \&Get;
    $hash->{AttrFn}  = \&Attr;
    $hash->{ReadFn}  = \&Read;
    $hash->{WriteFn} = \&Write;

    # Da dies kein 2 stuffiges Modul ist brauchst Du das hier nicht
    $hash->{Clients}   = ':EaseeWallbox:';
    $hash->{MatchList} = { '1:EaseeWallbox' => '^EaseeWallbox;.*' };

    $hash->{AttrList} =
        'expertMode:yes,no '
      . 'ledStuff:yes,no '
      . 'SmartCharging:true,false '
      . $readingFnAttributes;

    Log 3, "EaseeWallbox module initialized.";

    return;    # Jede Funktion muss mit einem return enden
}

sub Define {
    my ( $hash, $def ) = @_;

    # set API URI as Internal Key
    $hash->{APIURI} = 'https://api.easee.cloud/api/';

    return;
}

sub Undef {
    my ( $hash, $arg ) = @_;

    return;
}

sub Get {
    my ( $hash, $name, @args ) = @_;

    return;
}

sub Set {
    my ( $hash, $name, @param ) = @_;

    return;
}

sub WriteToCloudAPI {
    my $hash   = shift;
    my $dpoint = shift;

    # ...
    # ...
    # $method ist GET oder POST
    # bei POST ist $payload gleich data

    ::HttpUtils_NonblockingGet(
        {
            url                => $hash->{URL} . $dpoints{$dpoint},
            timeout            => 15,
            incrementalTimeout => 1,
            hash               => $hash,
            dpoint             => $dpoint,
            device_id          => $deviceId,
            data               => $payload,
            method             => $method,
            header             => $header,
            callback           => \&ResponseHandling
        }
    );

    return;
}

sub ResponseHandling {
    my $param = shift;
    my $err   = shift;
    my $data  = shift;

# Nach Auswertung von err kannst Du anhand von $param->{dpoint} eine Auswertung der Daten machen

    #...
    #...

    return;
}

1;

=pod
=begin html


=end html

=cut