# --
# Copyright (C) 2001-2016 OTRS AG, http://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (AGPL). If you
# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
# --

package Kernel::System::OTRSBusiness;

use strict;
use warnings;

use Kernel::System::VariableCheck qw(:all);

our @ObjectDependencies = (
    'Kernel::Config',
    'Kernel::System::Cache',
    'Kernel::System::CloudService::Backend::Run',
    'Kernel::System::DynamicField',
    'Kernel::System::DynamicField::Backend',
    'Kernel::System::Log',
    'Kernel::System::DB',
    'Kernel::System::Package',
    'Kernel::System::SystemData',
    'Kernel::System::Time',
);

# If we cannot connect to cloud.otrs.com for more than the first period, show a warning.
my $NoConnectWarningPeriod = 60 * 60 * 24 * 5;    # 5 days

# If we cannot connect to cloud.otrs.com for more than the second period, show an error.
my $NoConnectErrorPeriod = 60 * 60 * 24 * 15;     # 15 days

# If the contract is about to expire in less than this time, show a hint
my $ContractExpiryWarningPeriod = 60 * 60 * 24 * 28;    # 28 days

=head1 NAME

Kernel::System::OTRSBusiness - OTRSBusiness deployment backend

=head1 SYNOPSIS

=head1 PUBLIC INTERFACE

=over 4

=cut

=item new()

create an object. Do not use it directly, instead use:

    use Kernel::System::ObjectManager;
    local $Kernel::OM = Kernel::System::ObjectManager->new();
    my $RegistrationObject = $Kernel::OM->Get('Kernel::System::OTRSBusiness');


=cut

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    #$Self->{APIVersion} = 1;

    # Get config object
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

    # Get OTRSBusiness::ReleaseChannel from SysConfig (Stable = 1, Development = 0)
    $Self->{OnlyStable} = $ConfigObject->Get('OTRSBusiness::ReleaseChannel') // 1;

    # Set cache params
    $Self->{CacheType} = 'OTRSBusiness';
    $Self->{CacheTTL}  = 60 * 60 * 24 * 30;    # 30 days

    # Check if cloud services are disabled
    $Self->{CloudServicesDisabled} = $ConfigObject->Get('CloudServices::Disabled') || 0;

    return $Self;
}

=item OTRSBusinessIsInstalled()

checks if OTRSBusiness is installed in the current system.
That does not necessarily mean that it is also active, for
example if the package is only on the database but not on
the file system.

=cut

sub OTRSBusinessIsInstalled {
    my ( $Self, %Param ) = @_;

    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');

    # as the check for installed packages can be
    # very expensive, we want to use caching here
    my $Cache = $CacheObject->Get(
        Type => $Self->{CacheType},
        TTL  => $Self->{CacheTTL},
        Key  => 'OTRSBusinessIsInstalled',
    );

    return $Cache if defined $Cache;

    my $IsInstalled = $Self->_GetOTRSBusinessPackageFromRepository() ? 1 : 0;

    # set cache
    $CacheObject->Set(
        Type  => $Self->{CacheType},
        TTL   => $Self->{CacheTTL},
        Key   => 'OTRSBusinessIsInstalled',
        Value => $IsInstalled,
    );

    return $IsInstalled;
}

=item OTRSBusinessIsAvailable()

checks with cloud.otrs.com if OTRSBusiness is available for the current framework.

=cut

sub OTRSBusinessIsAvailable {
    my ( $Self, %Param ) = @_;

    return if $Self->{CloudServicesDisabled};

    my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run');
    my $RequestResult      = $CloudServiceObject->Request(
        RequestData => {
            OTRSBusiness => [
                {
                    Operation => 'BusinessVersionCheck',
                    Data      => {
                        OnlyStable => $Self->{OnlyStable},
                    },
                },
            ],
        },
    );

    my $OperationResult;
    if ( IsHashRefWithData($RequestResult) ) {
        $OperationResult = $CloudServiceObject->OperationResultGet(
            RequestResult => $RequestResult,
            CloudService  => 'OTRSBusiness',
            Operation     => 'BusinessVersionCheck',
        );

        if ( $OperationResult->{Success} ) {
            $Self->HandleBusinessVersionCheckCloudServiceResult(
                OperationResult => $OperationResult,
            );

            if ( $OperationResult->{Data}->{LatestVersionForCurrentFramework} ) {
                return 1;
            }
        }
    }
    return;
}

=item OTRSBusinessIsAvailableOffline()

retrieves the latest result of the BusinessVersionCheck cloud service
that was stored in the system_data table.

returns 1 if available.

=cut

sub OTRSBusinessIsAvailableOffline {
    my ( $Self, %Param ) = @_;

    my %BusinessVersionCheck = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet(
        Group => 'OTRSBusiness',
    );

    return $BusinessVersionCheck{LatestVersionForCurrentFramework} ? 1 : 0;
}

=item OTRSBusinessIsCorrectlyDeployed()

checks if the OTRSBusiness package is correctly
deployed or if it needs to be reinstalled.

=cut

sub OTRSBusinessIsCorrectlyDeployed {
    my ( $Self, %Param ) = @_;

    my $Package = $Self->_GetOTRSBusinessPackageFromRepository();

    # Package not found -> return failure
    return if !$Package;

    # first check the regular way if the files are present and the package
    # itself is installed correctly
    return if !$Kernel::OM->Get('Kernel::System::Package')->DeployCheck(
        Name    => $Package->{Name}->{Content},
        Version => $Package->{Version}->{Content},
    );

    # check if all tables have been created correctly
    # we can't rely on any .opm file here, so we just check
    # the list of tables manually
    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');

    TABLES:
    for my $Table (qw(chat chat_participant chat_message)) {

        # if a table does not exist, $TablePresent will be 'undef' for this table
        my $TablePresent = $DBObject->Do(
            SQL   => "SELECT * FROM $Table",
            Limit => 1,
        );

        return if !$TablePresent;
    }

    return 1;
}

=item OTRSBusinessIsReinstallable()

checks if the OTRSBusiness package can be reinstalled
(if it supports the current framework version). If not,
an update might be needed.

=cut

sub OTRSBusinessIsReinstallable {
    my ( $Self, %Param ) = @_;

    my $Package = $Self->_GetOTRSBusinessPackageFromRepository();

    # Package not found -> return failure
    return if !$Package;

    return $Kernel::OM->Get('Kernel::System::Package')->_CheckFramework(
        Framework => $Package->{Framework},
    );
}

=item OTRSBusinessIsUpdateable()

checks with cloud.otrs.com if the OTRSBusiness package is available in a newer version
than the one currently installed. The result of this check will be stored in the
system_data table for offline usage.

=cut

sub OTRSBusinessIsUpdateable {
    my ( $Self, %Param ) = @_;

    return 0 if $Self->{CloudServicesDisabled};

    my $Package = $Self->_GetOTRSBusinessPackageFromRepository();
    return if !$Package;

    my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run');
    my $RequestResult      = $CloudServiceObject->Request(
        RequestData => {
            OTRSBusiness => [
                {
                    Operation => 'BusinessVersionCheck',
                    Data      => {
                        OnlyStable => $Self->{OnlyStable},
                    },
                },
            ],
        },
    );

    my $OperationResult;
    if ( IsHashRefWithData($RequestResult) ) {
        $OperationResult = $CloudServiceObject->OperationResultGet(
            RequestResult => $RequestResult,
            CloudService  => 'OTRSBusiness',
            Operation     => 'BusinessVersionCheck',
        );

        if ( $OperationResult && $OperationResult->{Success} ) {

            $Self->HandleBusinessVersionCheckCloudServiceResult( OperationResult => $OperationResult );

            if ( $OperationResult->{Data}->{LatestVersionForCurrentFramework} ) {
                return $Kernel::OM->Get('Kernel::System::Package')->_CheckVersion(
                    VersionNew       => $OperationResult->{Data}->{LatestVersionForCurrentFramework},
                    VersionInstalled => $Package->{Version}->{Content},
                    Type             => 'Max',
                );
            }
        }
    }

    return 0;
}

=item OTRSBusinessVersionCheckOffline()

retrieves the latest result of the BusinessVersionCheck cloud service
that was stored in the system_data table.

    my %Result = $OTRSBusinessObject->OTRSBusinessVersionCheckOffline();

returns

    $Result = (
        OTRSBusinessUpdateAvailable      => 1,  # if applicable
        FrameworkUpdateAvailable         => 1,  # if applicable
    );

=cut

sub OTRSBusinessVersionCheckOffline {
    my ( $Self, %Param ) = @_;

    my $Package = $Self->_GetOTRSBusinessPackageFromRepository();
    return if !$Package;

    my %EntitlementData = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet(
        Group => 'OTRSBusiness',
    );

    my %Result = (
        FrameworkUpdateAvailable => $EntitlementData{FrameworkUpdateAvailable} // '',
    );

    if ( $EntitlementData{LatestVersionForCurrentFramework} ) {
        $Result{OTRSBusinessUpdateAvailable} = $Kernel::OM->Get('Kernel::System::Package')->_CheckVersion(
            VersionNew       => $EntitlementData{LatestVersionForCurrentFramework},
            VersionInstalled => $Package->{Version}->{Content},
            Type             => 'Max',
        );
    }

    return %Result;
}

=item OTRSBusinessGetDependencies()

checks if there are any active dependencies on OTRSBusiness.

=cut

sub OTRSBusinessGetDependencies {
    my ( $Self, %Param ) = @_;

    my @Packages = $Kernel::OM->Get('Kernel::System::Package')->RepositoryList();

    my @DependentPackages;
    PACKAGE:
    for my $Package (@Packages) {

        next PACKAGE if !IsHashRefWithData($Package);
        next PACKAGE if !IsArrayRefWithData( $Package->{PackageRequired} );

        DEPENDENCY:
        for my $Dependency ( @{ $Package->{PackageRequired} } ) {

            next DEPENDENCY if !IsHashRefWithData($Dependency);
            next DEPENDENCY if !$Dependency->{Content};
            next DEPENDENCY if $Dependency->{Content} ne 'OTRSBusiness';

            push @DependentPackages, {
                Name        => $Package->{Name}->{Content},
                Vendor      => $Package->{Vendor}->{Content},
                Version     => $Package->{Version}->{Content},
                Description => $Package->{Description},
            };

            last DEPENDENCY;
        }
    }

    return \@DependentPackages;
}

=item OTRSBusinessEntitlementCheck()

determines the OTRSBusiness entitlement status of this system as reported by cloud.otrs.com
and stores it in the system_data cache.

Returns 1 if the cloud call was successful.

=cut

sub OTRSBusinessEntitlementCheck {
    my ( $Self, %Param ) = @_;

    return if $Self->{CloudServicesDisabled};

    my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run');
    my $RequestResult      = $CloudServiceObject->Request(
        RequestData => {
            OTRSBusiness => [
                {
                    Operation => 'BusinessPermission',
                    Data      => {},
                },
            ],
        },
    );

    my $OperationResult;
    if ( IsHashRefWithData($RequestResult) ) {
        $OperationResult = $CloudServiceObject->OperationResultGet(
            RequestResult => $RequestResult,
            CloudService  => 'OTRSBusiness',
            Operation     => 'BusinessPermission',
        );
    }

    # OK, so we got a successful cloud call result. Then we will use it and remember it.
    if ( IsHashRefWithData($OperationResult) && $OperationResult->{Success} ) {

        # Store it in the SystemData so that it is also available for the notification modules,
        #   even before the first run of RegistrationUpdate.
        $Self->HandleBusinessPermissionCloudServiceResult(
            OperationResult => $OperationResult,
        );
        return 1;
    }

    if ( !IsHashRefWithData($RequestResult) || !$RequestResult->{Success} ) {
        my $Message = "BusinessPermission - Can't contact cloud.otrs.com server";
        $Kernel::OM->Get('Kernel::System::Log')->Log(
            Priority => 'error',
            Message  => $Message
        );
    }

    if ( !IsHashRefWithData($OperationResult) || !$OperationResult->{Success} ) {
        my $Message = "BusinessPermission - could not perform BusinessPermission check";
        if ( IsHashRefWithData($OperationResult) ) {
            $Message .= $OperationResult->{ErrorMessage};
        }
        $Kernel::OM->Get('Kernel::System::Log')->Log(
            Priority => 'error',
            Message  => $Message
        );
    }

    return 0;
}

=item OTRSBusinessEntitlementStatus()

Returns the current entitlement status.

    my $Status = $OTRSBusinessObject->OTRSBusinessEntitlementStatus(
        CallCloudService => 1,  # 0 or 1, call the cloud service before looking at the cache
    );

    $Status = 'entitled';   # everything is OK
    $Status = 'warning';    # last check was OK, and we are in the waiting period
    $Status = 'forbidden';  # not entitled (either because the server said so or because the last check was too long ago)

=cut

sub OTRSBusinessEntitlementStatus {
    my ( $Self, %Param ) = @_;

    # If the system is not registered, it cannot have an OB permission.
    #   Also, the BusinessPermissionChecks will not work any more, so the permission
    #   would expire after our waiting period. But in this case we can immediately deny
    #   the permission.
    my $RegistrationState = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGet(
        Key => 'Registration::State',
    );
    if ( !$RegistrationState || $RegistrationState ne 'registered' ) {
        return 'forbidden';
    }

    if ( $Param{CallCloudService} ) {
        $Self->OTRSBusinessEntitlementCheck();
    }

    # OK. Let's look at the system_data cache now and use it if appropriate
    my %EntitlementData = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet(
        Group => 'OTRSBusiness',
    );

    if ( !%EntitlementData || !$EntitlementData{BusinessPermission} ) {
        return 'forbidden';
    }

    # Check when the last successful BusinessPermission check was made.
    my $LastUpdateSystemTime = $Kernel::OM->Get('Kernel::System::Time')->TimeStamp2SystemTime(
        String => $EntitlementData{LastUpdateTime},
    );

    my $SecondsSinceLastUpdate = $Kernel::OM->Get('Kernel::System::Time')->SystemTime() - $LastUpdateSystemTime;

    if ( $SecondsSinceLastUpdate > $NoConnectErrorPeriod ) {
        return 'forbidden';
    }
    if ( $SecondsSinceLastUpdate > $NoConnectWarningPeriod ) {
        return 'warning';
    }

    return 'entitled';
}

=item OTRSBusinessContractExpiryDateCheck()

checks for the warning period before the contract expires

    my $ExpiryDate = $OTRSBusinessObject->OTRSBusinessContractExpiryDateCheck();

returns the ExpiryDate if a warning should be displayed

    $ExpiryDate = undef;                    # everything is OK, no warning
    $ExpiryDate = '2012-12-12 12:12:12'     # contract is about to expire, issue warning

=cut

sub OTRSBusinessContractExpiryDateCheck {
    my ( $Self, %Param ) = @_;

    if ( $Param{CallCloudService} ) {
        $Self->OTRSBusinessEntitlementCheck();
    }

    # OK. Let's look at the system_data cache now and use it if appropriate
    my %EntitlementData = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet(
        Group => 'OTRSBusiness',
    );

    if ( !%EntitlementData || !$EntitlementData{ExpiryDate} ) {
        return;
    }

    my $ExpiryDateSystemTime = $Kernel::OM->Get('Kernel::System::Time')->TimeStamp2SystemTime(
        String => $EntitlementData{ExpiryDate},
    );

    my $SecondsUntilExpiryDate = $ExpiryDateSystemTime - $Kernel::OM->Get('Kernel::System::Time')->SystemTime();

    if ( $SecondsUntilExpiryDate < $ContractExpiryWarningPeriod ) {
        return $EntitlementData{ExpiryDate};
    }

    return;
}

sub HandleBusinessPermissionCloudServiceResult {
    my ( $Self, %Param ) = @_;

    my $OperationResult = $Param{OperationResult};

    return if !$OperationResult->{Success};

    # We store the current time as LastUpdateTime so that we know when the last
    #   permission check could be successfully made with the server. This is needed
    #   to determine if the results can still be used later, if a connection to
    #   cloud.otrs.com cannot be made temporarily.
    my %StoreData = (
        BusinessPermission => $OperationResult->{Data}->{BusinessPermission} // 0,
        ExpiryDate         => $OperationResult->{Data}->{ExpiryDate}         // '',
        LastUpdateTime     => $Kernel::OM->Get('Kernel::System::Time')->SystemTime2TimeStamp(
            SystemTime => $Kernel::OM->Get('Kernel::System::Time')->SystemTime()
        ),
    );

    my $SystemDataObject = $Kernel::OM->Get('Kernel::System::SystemData');

    for my $Key ( sort keys %StoreData ) {
        my $FullKey = 'OTRSBusiness::' . $Key;

        if ( defined $SystemDataObject->SystemDataGet( Key => $FullKey ) ) {
            $SystemDataObject->SystemDataUpdate(
                Key    => $FullKey,
                Value  => $StoreData{$Key},
                UserID => 1,
            );
        }
        else {
            $SystemDataObject->SystemDataAdd(
                Key    => $FullKey,
                Value  => $StoreData{$Key},
                UserID => 1,
            );
        }
    }

    return 1;
}

sub HandleBusinessVersionCheckCloudServiceResult {
    my ( $Self, %Param ) = @_;

    my $OperationResult = $Param{OperationResult};

    return if !$OperationResult->{Success};

    my %StoreData = (
        LatestVersionForCurrentFramework => $OperationResult->{Data}->{LatestVersionForCurrentFramework} // '',
        FrameworkUpdateAvailable         => $OperationResult->{Data}->{FrameworkUpdateAvailable}         // '',
    );

    my $SystemDataObject = $Kernel::OM->Get('Kernel::System::SystemData');

    for my $Key ( sort keys %StoreData ) {
        my $FullKey = 'OTRSBusiness::' . $Key;

        if ( defined $SystemDataObject->SystemDataGet( Key => $FullKey ) ) {
            $SystemDataObject->SystemDataUpdate(
                Key    => $FullKey,
                Value  => $StoreData{$Key},
                UserID => 1,
            );
        }
        else {
            $SystemDataObject->SystemDataAdd(
                Key    => $FullKey,
                Value  => $StoreData{$Key},
                UserID => 1,
            );
        }
    }

    return 1;
}

sub _OTRSBusinessFileGet {
    my ( $Self, %Param ) = @_;

    return if $Self->{CloudServicesDisabled};

    my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run');
    my $RequestResult      = $CloudServiceObject->Request(
        RequestData => {
            OTRSBusiness => [
                {
                    Operation => 'BusinessFileGet',
                    Data      => {
                        OnlyStable => $Self->{OnlyStable},
                    },
                },
            ],
        },
    );

    my $OperationResult;
    if ( IsHashRefWithData($RequestResult) ) {
        $OperationResult = $CloudServiceObject->OperationResultGet(
            RequestResult => $RequestResult,
            CloudService  => 'OTRSBusiness',
            Operation     => 'BusinessFileGet',
        );

        if ( $OperationResult->{Success} && $OperationResult->{Data}->{Package} ) {
            return $OperationResult->{Data}->{Package};
        }
    }

    return;
}

=item OTRSBusinessInstall()

downloads and installs OTRSBusiness.

=cut

sub OTRSBusinessInstall {
    my ( $Self, %Param ) = @_;

    my $PackageString = $Self->_OTRSBusinessFileGet();
    return if !$PackageString;

    my $Install = $Kernel::OM->Get('Kernel::System::Package')->PackageInstall(
        String    => $PackageString,
        FromCloud => 1,
    );

    return $Install if !$Install;

    # now that we know that OTRSBusiness has been installed,
    # we can just preset the cache instead of just swiping it.
    $Kernel::OM->Get('Kernel::System::Cache')->Set(
        Type  => $Self->{CacheType},
        TTL   => $Self->{CacheTTL},
        Key   => 'OTRSBusinessIsInstalled',
        Value => 1,
    );

    return $Install;
}

=item OTRSBusinessReinstall()

reinstalls OTRSBusiness from local repository.

=cut

sub OTRSBusinessReinstall {
    my ( $Self, %Param ) = @_;

    my $Package = $Self->_GetOTRSBusinessPackageFromRepository();

    # Package not found -> return failure
    return if !$Package;

    my $PackageString = $Kernel::OM->Get('Kernel::System::Package')->RepositoryGet(
        Name    => $Package->{Name}->{Content},
        Version => $Package->{Version}->{Content},
    );

    return $Kernel::OM->Get('Kernel::System::Package')->PackageReinstall(
        String => $PackageString,
    );
}

=item OTRSBusinessUpdate()

downloads and updates OTRSBusiness.

=cut

sub OTRSBusinessUpdate {
    my ( $Self, %Param ) = @_;

    my $PackageString = $Self->_OTRSBusinessFileGet();
    return if !$PackageString;

    return $Kernel::OM->Get('Kernel::System::Package')->PackageUpgrade(
        String    => $PackageString,
        FromCloud => 1,
    );
}

=item OTRSBusinessUninstall()

removes OTRSBusiness from the system.

=cut

sub OTRSBusinessUninstall {
    my ( $Self, %Param ) = @_;

    my $Package = $Self->_GetOTRSBusinessPackageFromRepository();

    # Package not found -> return failure
    return if !$Package;

    # TODO: the following code is now Deprecated and should be removed in further versions of OTRS
    # get a list of all dynamic fields for ticket and article
    my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField');
    my $DynamicFieldList   = $DynamicFieldObject->DynamicFieldListGet(
        Valid      => 0,
        ObjectType => [ 'Ticket', 'Article' ],
    );

    # filter only dynamic fields added by OTRSBusiness
    my %OTRSBusinessDynamicFieldTypes = (
        ContactWithData => 1,
        Database        => 1,
    );

    my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');

    DYNAMICFIELD:
    for my $DynamicFieldConfig ( @{$DynamicFieldList} ) {
        next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
        next DYNAMICFIELD if !$OTRSBusinessDynamicFieldTypes{ $DynamicFieldConfig->{FieldType} };

        # remove data from the field
        my $ValuesDeleteSuccess = $DynamicFieldBackendObject->AllValuesDelete(
            DynamicFieldConfig => $DynamicFieldConfig,
            UserID             => 1,
        );

        if ( !$ValuesDeleteSuccess ) {
            $Kernel::OM->Get('Kernel::System::Log')->Log(
                Priority => 'error',
                Message  => "Values from dynamic field $DynamicFieldConfig->{Name} could not be deleted!",
            );
        }

        my $Success = $DynamicFieldObject->DynamicFieldDelete(
            ID      => $DynamicFieldConfig->{ID},
            UserID  => 1,
            Reorder => 1,
        );

        if ( !$Success ) {
            $Kernel::OM->Get('Kernel::System::Log')->Log(
                Priority => 'error',
                Message  => "Dynamic field $DynamicFieldConfig->{Name} could not be deleted!",
            );
        }
    }

    # TODO: end Deprecated

    my $PackageString = $Kernel::OM->Get('Kernel::System::Package')->RepositoryGet(
        Name    => $Package->{Name}->{Content},
        Version => $Package->{Version}->{Content},
    );

    my $Uninstall = $Kernel::OM->Get('Kernel::System::Package')->PackageUninstall(
        String => $PackageString,
    );

    return $Uninstall if !$Uninstall;

    # now that we know that OTRSBusiness has been uninstalled,
    # we can just preset the cache instead of just swiping it.
    $Kernel::OM->Get('Kernel::System::Cache')->Set(
        Type  => $Self->{CacheType},
        TTL   => $Self->{CacheTTL},
        Key   => 'OTRSBusinessIsInstalled',
        Value => 0,
    );

    return $Uninstall;
}

=item OTRSBusinessCommandNextUpdateTimeSet()

Set the next update time for the given command in the system data table storage.

    my $Success = $OTRSBusinessObject->OTRSBusinessCommandNextUpdateTimeSet(
        Command => 'AvailabilityCheck',
    );

Returns 1 if the next update time was set successfully.

=cut

sub OTRSBusinessCommandNextUpdateTimeSet {
    my ( $Self, %Param ) = @_;

    return if !$Param{Command};

    my $Key = "OTRSBusiness::$Param{Command}::NextUpdateTime";

    my $SystemDataObject = $Kernel::OM->Get('Kernel::System::SystemData');

    my $NextUpdateTime = $SystemDataObject->SystemDataGet(
        Key => $Key,
    );

    # set the default next update seconds offset
    my $NextUpdateSecondsOffset = 60 * 60 * 24;

    # generate a random seconds offset, if no next update time exists
    if ( !$NextUpdateTime ) {

        # create the random numbers
        my $RandomHour   = int 20 + rand 23 - 20;
        my $RandomMinute = int rand 60;

        # create the random seconds offset
        $NextUpdateSecondsOffset = 60 * 60 * $RandomHour + ( 60 * $RandomMinute );
    }

    # get time object
    my $TimeObject = $Kernel::OM->Get('Kernel::System::Time');

    my $CalculatedNextUpdateTime = $TimeObject->SystemTime2TimeStamp(
        SystemTime => $TimeObject->SystemTime() + $NextUpdateSecondsOffset,
    );

    if ( defined $NextUpdateTime ) {
        $SystemDataObject->SystemDataUpdate(
            Key    => $Key,
            Value  => $CalculatedNextUpdateTime,
            UserID => 1,
        );
    }
    else {
        $SystemDataObject->SystemDataAdd(
            Key    => $Key,
            Value  => $CalculatedNextUpdateTime,
            UserID => 1,
        );
    }

    return 1;
}

sub _GetOTRSBusinessPackageFromRepository {
    my ( $Self, %Param ) = @_;

    my $PackageObject = $Kernel::OM->Get('Kernel::System::Package');

    my @RepositoryList = $PackageObject->RepositoryList();

    for my $Package (@RepositoryList) {
        return $Package if $Package->{Name}->{Content} eq 'OTRSBusiness';
    }

    return;
}

1;

=back

=head1 TERMS AND CONDITIONS

This software is part of the OTRS project (L<http://otrs.org/>).

This software comes with ABSOLUTELY NO WARRANTY. For details, see
the enclosed file COPYING for license information (AGPL). If you
did not receive this file, see L<http://www.gnu.org/licenses/agpl.txt>.

=cut
