# --------------------------------------------------------------------------------------- #
#                                                                                         #
# The following two methods need to be added to                                           #
# Kernel::System::ITSMConfigItem                                                          #
#                                                                                         #
# --------------------------------------------------------------------------------------- #

=item CIEventHandlerPost()

call config item event post handler, returns nothing

    $TicketObject->CIEventHandlerPost(
        Event => 'VersionAdd',      #ConfigItemAdd || VersionAdd
        UserID => 456,
        ConfigItemID => 123,
        ClassID => 123              #optional
        DefinitionID => 123,        #optional
        Name => 'HAL-390',          #optional
        StateID => 456,             #optional
        XMLData => $ArrayHaschRef,  #optional
    );

events available:

ConfigItemAdd, VersionAdd;

=cut

sub CIEventHandlerPost {
    my $Self = shift;
    my %Param = @_;
    # check needed stuff
    foreach (qw(Event UserID)) {
        if (!$Param{$_}) {
            $Self->{LogObject}->Log(Priority => 'error', Message => "Need $_!");
            return;
        }
    }

    #load config item event module...
    my $Modules = $Self->{ConfigObject}->Get('ITSMConfigItem::EventModulePost');
    if ($Modules) {
        foreach my $Module (sort keys %{$Modules}) {
            if (!$Modules->{$Module}->{Event} || $Param{Event} =~ /$Modules->{$Module}->{Event}/i) {
                if ($Self->{MainObject}->Require($Modules->{$Module}->{Module})) {
                    my $Generic = $Modules->{$Module}->{Module}->new(
                        %{$Self},
                        ConfigItemObject => $Self,
                    );
                    $Generic->Run(
                        %Param,
                        Config => $Modules->{$Module},
                    );
                }
            }
        }
    }
}


=item CIEventHandlerPre()

call config item event pre handler, returns only a value if the called module returns something.
CI-Pre-Events may be used for plausiblity checks before inserting a new version.

    $TicketObject->CIEventHandlerPre(
        Event => 'VersionAdd',      #ConfigItemAdd || VersionAdd
        UserID => 456,
        ConfigItemID => 123,
        ClassID => 123              #optional
        DefinitionID => 123,        #optional
        Name => 'HAL-390',          #optional
        StateID => 456,             #optional
        XMLData => $ArrayHaschRef,  #optional
    );

events available:

ConfigItemAdd, VersionAdd;

=cut

sub CIEventHandlerPre {
    my $Self = shift;
    my %Param = @_;
    # check needed stuff
    foreach (qw(Event UserID)) {
        if (!$Param{$_}) {
            $Self->{LogObject}->Log(Priority => 'error', Message => "Need $_!");
            return;
        }
    }

    #load config item event module...
    my $Modules = $Self->{ConfigObject}->Get('ITSMConfigItem::EventModulePre');
    if ($Modules) {
        foreach my $Module (sort keys %{$Modules}) {
            if (!$Modules->{$Module}->{Event} || $Param{Event} =~ /$Modules->{$Module}->{Event}/i) {
                if ($Self->{MainObject}->Require($Modules->{$Module}->{Module})) {
                    my $Generic = $Modules->{$Module}->{Module}->new(
                        %{$Self},
                        ConfigItemObject => $Self,
                    );
                    my $Result = $Generic->Run(
                        %Param,
                        Config => $Modules->{$Module},
                    );
                    if( keys(%{$Result})) {
                    	return $Result;
                    }
                }
            }
        }
    }
}



# --------------------------------------------------------------------------------------- #
#                                                                                         #
# adaption of Kernel/System/ITSMConfigItem/Version.pm                                     #
#                                                                                         #
# --------------------------------------------------------------------------------------- #
=item VersionAdd()

add a new version

    my $VersionID = $ConfigItemObject->VersionAdd(
        ConfigItemID => 123,
        Name         => 'The Name',
        DefinitionID => 1212,
        DeplStateID  => 8,
        InciStateID  => 4,
        XMLData      => $ArrayHashRef,  # (optional)
        UserID       => 1,
    );

=cut

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

    # check needed stuff
    for my $Attribute (qw(ConfigItemID Name DefinitionID DeplStateID InciStateID UserID)) {
        if ( !$Param{$Attribute} ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $Attribute!" );
            return;
        }
    }

    # -----------------------------------------------------------------#
    # capeIT - run pre-event-handler....
    my $Result = $Self->CIEventHandlerPre(
        Event => 'VersionAdd',
        ConfigItemID => $Param{ConfigItemID},
        UserID => $Param{UserID},
        Name => $Param{Name},
        DefinitionID => $Param{DefinitionID},
        UsedVersionID => $Param{UsedVersionID} || 0,
        StateID => $Param{StateID},
        XMLData => $Param{XMLData},        
    );
    
    if( (ref($Result) eq 'HASH') && ($Result->{Error})) {
        $Self->{LogObject}->Log(
            Priority => 'notice', 
            Message => "Pre-VersionAdd refused version update.",
        );
    	return $Result;
    }
    #
    # NOTE:
    # it might be worth to think about putting the following state 
    # checks into a pre-event. However, for now they are left as they
    # are.
    #
    # EO capeIT - ...run pre-event-handler
    # -----------------------------------------------------------------#


    # get deployment state list
    my $DeplStateList = $Self->{GeneralCatalogObject}->ItemList(
        Class => 'ITSM::ConfigItem::DeploymentState',
    );

    return if !$DeplStateList;
    return if ref $DeplStateList ne 'HASH';

    # check the deployment state id
    if ( !$DeplStateList->{ $Param{DeplStateID} } ) {

        $Self->{LogObject}->Log(
            Priority => 'error',
            Message  => "No valid deployment state id given!",
        );
        return;
    }

    # get incident state list
    my $InciStateList = $Self->{GeneralCatalogObject}->ItemList(
        Class => 'ITSM::ConfigItem::IncidentState',
    );

    return if !$InciStateList;
    return if ref $InciStateList ne 'HASH';

    # check the incident state id
    if ( !$InciStateList->{ $Param{InciStateID} } ) {

        $Self->{LogObject}->Log(
            Priority => 'error',
            Message  => "No valid incident state id given!",
        );
        return;
    }

    # quote
    $Param{Name} = $Self->{DBObject}->Quote( $Param{Name} );
    for my $Attribute (qw(ConfigItemID DefinitionID DeplStateID InciStateID UserID)) {
        $Param{$Attribute} = $Self->{DBObject}->Quote( $Param{$Attribute}, 'Integer' );
    }

    # get config item
    my $ConfigItem = $Self->ConfigItemGet(
        ConfigItemID => $Param{ConfigItemID},
    );

    return if !$ConfigItem;
    return if ref $ConfigItem ne 'HASH';

    # insert new version
    my $Success = $Self->{DBObject}->Do(
        SQL => "INSERT INTO configitem_version "
            . "(configitem_id, name, definition_id, "
            . "depl_state_id, inci_state_id, create_time, create_by) VALUES "
            . "($Param{ConfigItemID}, '$Param{Name}', $Param{DefinitionID}, "
            . "$Param{DeplStateID}, $Param{InciStateID}, current_timestamp, $Param{UserID})"
    );

    return if !$Success;

    # get id of new version
    $Self->{DBObject}->Prepare(
        SQL => "SELECT id, create_time FROM configitem_version WHERE "
            . "configitem_id = $Param{ConfigItemID} ORDER BY id DESC",
        Limit => 1,
    );

    # fetch the result
    my $VersionID;
    my $CreateTime;
    while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
        $VersionID  = $Row[0];
        $CreateTime = $Row[1];
    }

    # check version id
    if ( !$VersionID ) {
        $Self->{LogObject}->Log(
            Priority => 'error',
            Message  => "Can't get the new version id!",
        );
        return;
    }

    # add xml data
    if ( $Param{XMLData} && ref $Param{XMLData} eq 'ARRAY' ) {
        $Self->_XMLVersionAdd(
            ClassID      => $ConfigItem->{ClassID},
            ConfigItemID => $Param{ConfigItemID},
            VersionID    => $VersionID,
            XMLData      => $Param{XMLData},
        );
    }

    # update last_version_id, cur_depl_state_id, cur_inci_state_id, change_time and change_by
    $Self->{DBObject}->Do(
        SQL => "UPDATE configitem SET last_version_id = $VersionID,"
            . "cur_depl_state_id = $Param{DeplStateID}, "
            . "cur_inci_state_id = $Param{InciStateID}, "
            . "change_time = '$CreateTime', change_by = $Param{UserID} "
            . "WHERE id = $Param{ConfigItemID}"
    );


    # -----------------------------------------------------------------#
    # capeIT - run post-event-handler....
    $Self->CIEventHandlerPost(
        Event => 'VersionAdd',
        ConfigItemID => $Param{ConfigItemID},
        UserID => $Param{UserID},
        Name => $Param{Name},
        DefinitionID => $Param{DefinitionID},
        StateID => $Param{StateID},
        XMLData => $Param{XMLData},        
    );
    #
    # NOTE:
    # it might be worth to think about putting the following  
    # action into a post-event. However, for now it is left as it is.
    #
    # EO capeIT - ...run post-event-handler
    # -----------------------------------------------------------------#

    # recalculate the current incident state of alle linked config items
    $Self->CurInciStateRecalc(
        ConfigItemID => $Param{ConfigItemID},
    );

    return $VersionID;
}






# --------------------------------------------------------------------------------------- #
#                                                                                         #
# adaption of Kernel/System/ITSMConfigItem.pm                                             #
#                                                                                         #
# --------------------------------------------------------------------------------------- #

=item ConfigItemAdd()

add a new config item

    my $ConfigItemID = $ConfigItemObject->ConfigItemAdd(
        Number  => '111',  # (optional)
        ClassID => 123,
        UserID  => 1,
    );

=cut

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

    # check needed stuff
    for my $Argument (qw(ClassID UserID)) {
        if ( !$Param{$Argument} ) {
            $Self->{LogObject}->Log(
                Priority => 'error',
                Message  => "Need $Argument!"
            );
            return;
        }
    }

    # get class list
    my $ClassList = $Self->{GeneralCatalogObject}->ItemList(
        Class => 'ITSM::ConfigItem::Class',
    );

    return if !$ClassList;
    return if ref $ClassList ne 'HASH';

    # check the class id
    if ( !$ClassList->{ $Param{ClassID} } ) {

        $Self->{LogObject}->Log(
            Priority => 'error',
            Message  => "No valid class id given!",
        );
        return;
    }

    # quote
    for my $Argument (qw(ClassID UserID)) {
        $Param{$Argument} = $Self->{DBObject}->Quote( $Param{$Argument}, 'Integer' );
    }

    # -----------------------------------------------------------------#
    # capeIT - run pre-event-handler....
    #
    # So far there is no idea about the use of a pre-config-item-add 
    # event - maybe generating the CI-number?
    #
    # EO capeIT - ...run pre-event-handler
    # -----------------------------------------------------------------#

    # create config item number
    if ( $Param{Number} ) {

        # quote
        $Param{Number} = $Self->{DBObject}->Quote( $Param{Number} );

        # find existing config item number
        my $Exists = $Self->ConfigItemNumberLookup(
            ConfigItemNumber => $Param{Number},
        );

        if ($Exists) {
            $Self->{LogObject}->Log(
                Priority => 'error',
                Message  => 'Config item number already exists!',
            );
            return;
        }
    }
    else {

        # create config item number
        $Param{Number} = $Self->ConfigItemNumberCreate(
            Type    => $Self->{ConfigObject}->Get('ITSMConfigItem::NumberGenerator'),
            ClassID => $Param{ClassID},
        );
    }

    $Self->CIEventHandlerPre(
        Event => 'ConfigItemAdd',
        UserID => $Param{UserID},
        ConfigItemID => '',
    ); 


    # insert new config item
    my $Success = $Self->{DBObject}->Do(
        SQL => "INSERT INTO configitem "
            . "(configitem_number, class_id, create_time, create_by, change_time, change_by) "
            . "VALUES ('$Param{Number}', $Param{ClassID}, current_timestamp, "
            . "$Param{UserID}, current_timestamp, $Param{UserID})"
    );

    return if !$Success;

    # find id of new item
    $Self->{DBObject}->Prepare(
        SQL => "SELECT id FROM configitem WHERE "
            . "configitem_number = '$Param{Number}' AND class_id = $Param{ClassID} "
            . " ORDER BY id DESC",
        Limit => 1,
    );

    # -----------------------------------------------------------------#
    # capeIT - run post-event-handler....
    $Self->CIEventHandlerPost(
        Event => 'ConfigItemAdd',
        UserID => $Param{UserID},
        ConfigItemID => $ConfigItemID,
    );
    #
    # EO capeIT - ...run post-event-handler
    # -----------------------------------------------------------------#

    # fetch the result
    my $ConfigItemID;
    while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
        $ConfigItemID = $Row[0];
    }

    return $ConfigItemID;
}





# --------------------------------------------------------------------------------------- #
#                                                                                         #
# adaption of Kernel/Config/Files/CIEventRegistration.xml                                 #
#                                                                                         #
# --------------------------------------------------------------------------------------- #


<?xml version="1.0" encoding="iso-8859-1" ?>
<otrs_config version="1.0" init="Config">
    <CVS>$Id: ITSMConfigItemEvents.xml,v 1.4 2008-07-02 16:53:47 tto Exp $</CVS>
    <ConfigItem Name="ITSMConfigItem::EventModulePost###999-Test" Required="0" Valid="0">
        <Description Lang="en">ITSM Config Item Event test module.</Description>
        <Description Lang="de">ITSM Config Item Event Testmodul.</Description>
        <Group>ITSM</Group>
        <SubGroup>Core::ITSMConfigItem</SubGroup>
        <Setting>
            <Hash>
                <Item Key="Module">Kernel::System::ITSMConfigItem::Event::Test</Item>
                <Item Key="Event">(ConfigItemAdd|VersionAdd)</Item>
            </Hash>
        </Setting>
    </ConfigItem>
    <ConfigItem Name="ITSMConfigItem::EventModulePre###999-Test" Required="0" Valid="0">
        <Description Lang="en">ITSM Config Item Event test module.</Description>
        <Description Lang="de">ITSM Config Item Event Testmodul.</Description>
        <Group>ITSM</Group>
        <SubGroup>Core::ITSMConfigItem</SubGroup>
        <Setting>
            <Hash>
                <Item Key="Module">Kernel::System::ITSMConfigItem::Event::Test</Item>
                <Item Key="Event">(ConfigItemAdd|VersionAdd)</Item>
            </Hash>
        </Setting>
     </ConfigItem>
</otrs_config>





