<?php
/**
 * Automation UI
 *
 * @package     AutomatorWP\Automation_UI
 * @author      AutomatorWP <contact@automatorwp.com>, Ruben Garcia <rubengcdev@gmail.com>
 * @since       1.0.0
 */
// Exit if accessed directly
if( !defined( 'ABSPATH' ) ) exit;

/**
 * Render automation type dialog
 *
 * @since 1.3.0
 */
function automatorwp_render_automation_type_dialog() {

    if( ! isset( $_GET['page'] ) ) {
        return;
    }

    $allowed_pages = array(
        'automatorwp_automations',
        'edit_automatorwp_automations',
    );

    // Only render on allowed pages
    if( ! in_array( $_GET['page'], $allowed_pages ) ) {
        return;
    }

    $types = automatorwp_get_automation_types(); ?>

    <div class="automatorwp-automation-type-dialog-wrapper" style="display: none;">

        <div class="automatorwp-automation-type-dialog">
            <h2 class="automatorwp-automation-type-dialog-title"><?php esc_html_e( 'Automation type', 'automatorwp' ); ?></h2>
            <div class="automatorwp-automation-types">
                <?php foreach( $types as $type => $args ) :
                    if( in_array( $type, automatorwp_get_automation_loop_types() ) ) continue; ?>
                    <div class="automatorwp-automation-type automatorwp-automation-type-<?php echo $type; ?>" data-type="<?php echo $type; ?>">
                        <img src="<?php echo $args['image']; ?>" alt="<?php echo $args['label']; ?>">
                        <div class="automatorwp-automation-type-description">
                            <strong><?php echo $args['label']; ?></strong>
                            <span><?php echo $args['desc']; ?></span>
                        </div>
                    </div>
                <?php endforeach; ?>
            </div>
            <h3 class="automatorwp-automation-type-dialog-automation-loop-title">
                <?php esc_html_e( 'Loop Automations', 'automatorwp' ); ?>
                <span class="cmb-tooltip">
                    <i class="dashicons dashicons-cmb-tooltip"></i>
                    <span class="cmb-tooltip-desc cmb-tooltip-top"><?php _e( 'Designed to run actions on a <b>group of elements</b>. Can be run <b>manually</b>, on a <b>specific date</b> or on a <b>recurring</b> basis.', 'automatorwp' ); ?></span>
                </span>
            </h3>
            <div class="automatorwp-automation-types automatorwp-automation-loop-types">
                <?php foreach( $types as $type => $args ) :
                    if( ! in_array( $type, automatorwp_get_automation_loop_types() ) ) continue; ?>
                    <div class="automatorwp-automation-type automatorwp-automation-type-<?php echo $type; ?>" data-type="<?php echo $type; ?>">
                        <img src="<?php echo $args['image']; ?>" alt="<?php echo $args['label']; ?>">
                        <div class="automatorwp-automation-type-description">
                            <strong><?php echo $args['label']; ?></strong>
                            <span><?php echo $args['desc']; ?></span>
                        </div>
                    </div>
                <?php endforeach; ?>
            </div>
            <div class="automatorwp-notice-warning">
                <?php echo __( '<strong>Note:</strong> Automation type cannot be changed later. ', 'automatorwp' ); ?>
            </div>
            <div class="automatorwp-dialog-bottom automatorwp-automation-type-dialog-bottom">
                <div class="automatorwp-dialog-buttons automatorwp-automation-type-dialog-buttons">
                    <button type="button" class="button button-primary automatorwp-automation-type-dialog-confirm"><?php _e( 'Confirm', 'automatorwp' ); ?></button>
                    <button type="button" data-dialog="automatorwp-automation-type-dialog" class="button automatorwp-button-danger automatorwp-dialog-cancel automatorwp-automation-type-dialog-cancel"><?php _e( 'Cancel', 'automatorwp' ); ?></button>
                </div>
            </div>
        </div>

    </div>

    <?php

}
add_action( 'admin_footer', 'automatorwp_render_automation_type_dialog' );

/**
 * Render automation url export dialog
 *
 * @since 1.4.8
 */
function automatorwp_render_automation_url_export_dialog() {

    if( ! isset( $_GET['page'] ) ) {
        return;
    }

    $allowed_pages = array(
        'automatorwp_automations',
        'edit_automatorwp_automations',
    );

    // Only render on allowed pages
    if( ! in_array( $_GET['page'], $allowed_pages ) ) {
        return;
    } ?>

    <div class="automatorwp-automation-url-export-dialog-wrapper" style="display: none;">

        <div class="automatorwp-automation-url-export-dialog">
            <h2><?php _e( 'Export automation', 'automatorwp' ); ?></h2>
            <div class="automatorwp-automation-url-export-dialog-input">
                <label><?php _e( 'Enter you website URL:', 'automatorwp' ); ?></label>
                <input type="text" placeholder="https://website.com">
                <div class="automatorwp-notice-error" style="display: none;"><?php _e( 'Please, enter a valid URL.', 'automatorwp' ); ?></div>
            </div>
            <div class="automatorwp-automation-url-export-dialog-url">
                <label><?php _e( 'Exportable URL:', 'automatorwp' ); ?></label>
                <input type="text">
                <div class="automatorwp-automation-url-export-dialog-url-copy">
                    <div class="automatorwp-automation-url-export-dialog-url-copy-icon"><span class="dashicons dashicons-admin-page"></span></div>
                    <div class="automatorwp-automation-url-export-dialog-url-copy-text">
                        <span class="automatorwp-automation-url-export-dialog-url-copy-text-copy"><?php _e( 'Copy URL', 'automatorwp' ); ?></span>
                        <span class="automatorwp-automation-url-export-dialog-url-copy-text-copied" style="display: none;"><?php _e( 'Copied!', 'automatorwp' ); ?></span>
                    </div>
                </div>
                <span class="automatorwp-automation-url-export-dialog-desc"><?php _e( 'Copy this URL and place it on your browser to automatically import this automation on your website.', 'automatorwp' ); ?></span>
            </div>
            <div class="automatorwp-dialog-bottom automatorwp-automation-url-export-dialog-bottom">
                <div class="automatorwp-dialog-buttons automatorwp-automation-url-export-dialog-buttons">
                    <button type="button" class="button button-primary automatorwp-automation-url-export-dialog-confirm">
                        <span class="automatorwp-automation-url-export-dialog-confirm-default-text"><?php _e( 'Generate URL to export', 'automatorwp' ); ?></span>
                        <span class="automatorwp-automation-url-export-dialog-confirm-generating-text" style="display: none;"><?php _e( 'Generating URL', 'automatorwp' ); ?>...</span>
                        <span class="automatorwp-automation-url-export-dialog-confirm-success-text" style="display: none;"><?php _e( 'Done', 'automatorwp' ); ?></span>
                    </button>
                    <button type="button" data-dialog="automatorwp-automation-url-export-dialog" class="button automatorwp-button-danger automatorwp-dialog-cancel automatorwp-automation-url-export-dialog-cancel"><?php _e( 'Cancel', 'automatorwp' ); ?></button>
                </div>
            </div>
        </div>

    </div>

    <?php

}
add_action( 'admin_footer', 'automatorwp_render_automation_url_export_dialog' );

/**
 * Render automation type dialog
 *
 * @since 1.3.0
 *
 * @param string $classes
 *
 * @return string
 */
function automatorwp_automation_ui_admin_body_class( $classes ) {

    global $ct_table;

    if( ! isset( $_GET['page'] ) ) {
        return $classes;
    }

    // Only add class on allowed pages
    if( $_GET['page'] !== 'edit_automatorwp_automations' ) {
        return $classes;
    }

    if( $ct_table->name !== 'automatorwp_automations' ) {
        return $classes;
    }

    $primary_key = $ct_table->db->primary_key;

    if( ! isset( $_GET[$primary_key] ) ) {
        return $classes;
    }

    $automation_id = (int) $_GET[$primary_key];
    $automation = $ct_table->db->get( $automation_id );

    $classes .= ' edit-' . $automation->type . '-automation ';

    $classes = apply_filters( 'automatorwp_automation_ui_admin_body_class', $classes, $automation );

    return $classes;

}
add_filter( 'admin_body_class', 'automatorwp_automation_ui_admin_body_class' );

/**
 * Automation UI meta boxes
 *
 * @since  1.0.0
 */
function automatorwp_automation_ui_add_meta_boxes() {

    add_meta_box( 'automatorwp_triggers', __( 'Triggers', 'automatorwp' ), 'automatorwp_automation_ui_triggers_meta_box', 'automatorwp_automations', 'normal', 'default' );
    add_meta_box( 'automatorwp_actions', __( 'Actions', 'automatorwp' ), 'automatorwp_automation_ui_actions_meta_box', 'automatorwp_automations', 'normal', 'default' );

}
add_action( 'add_meta_boxes', 'automatorwp_automation_ui_add_meta_boxes' );

/**
 * Renders the triggers meta box
 *
 * @since  1.0.0
 *
 * @param stdClass $automation The automation object
 * @param string   $type       Type to render form
 */
function automatorwp_automation_ui_triggers_meta_box( $automation, $type ) {

    global $automatorwp_triggers_current_position;

    $automatorwp_triggers_current_position = 0;

    $triggers = automatorwp_get_automation_triggers( $automation->id );

    ?>
    <?php // Section title and subtitle ?>
    <div class="automatorwp-title"><?php _e( 'Triggers', 'automatorwp' ); ?></div>
    <div class="automatorwp-subtitle"><?php _e( 'When this happens...', 'automatorwp' ); ?></div>

    <?php // Sequential ?>
    <div class="automatorwp-sequential-field cmb2-switch">
        <label for="sequential"><?php _e( 'Sequential', 'automatorwp' ); ?></label>
        <div class="cmb-td">
            <input type="checkbox" id="sequential" name="sequential" class="automatorwp-auto-save" value="1" <?php checked( $automation->sequential, 1 ); ?> />
            <label for="sequential"><span class="cmb2-metabox-description"><?php _e( 'Check this option to force users to complete triggers in order.', 'automatorwp' ); ?></span></label>
        </div>
    </div>

    <?php // Triggers ?>
    <div class="automatorwp-automation-items automatorwp-triggers">

        <?php $triggers = automatorwp_check_automation_required_triggers( $automation, $triggers ); ?>

        <?php foreach( $triggers as $trigger ) : ?>

            <?php automatorwp_automation_item_edit_html( $trigger, 'trigger', $automation ); ?>

        <?php endforeach; ?>

    </div>

    <?php automatorwp_automation_ui_add_item_form( $automation, 'trigger' ); ?>

    <?php // Anonymous automation notice ?>
    <div class="automatorwp-automation-ui-anonymous-notice"><span class="dashicons dashicons-info"></span> <?php _e( 'Anonymous automations only support one trigger per automation.', 'automatorwp' ); ?></div>
    <?php // Add Trigger ?>
    <button type="button" class="button automatorwp-button-success automatorwp-add-trigger"><span class="dashicons dashicons-plus"></span><?php _e( 'Add Trigger', 'automatorwp' ); ?></button>
    <?php // Add Filter ?>
    <button type="button" class="button button-primary automatorwp-add-filter"><span class="dashicons dashicons-filter"></span><?php _e( 'Add Filter', 'automatorwp' ); ?></button>
    <?php // Box spinner ?>
    <div class="automatorwp-spinner automatorwp-box-spinner" style="display: none;">
        <span class="spinner is-active"></span>
        <span class="spinner-label"><?php _e( 'Saving...', 'automatorwp' ); ?></span>
    </div>
    <?php
}

/**
 * Renders the actions meta box
 *
 * @since  1.0.0
 *
 * @param stdClass $automation The automation object
 * @param string   $type       Type to render form
 */
function automatorwp_automation_ui_actions_meta_box( $automation, $type ) {

    $actions = automatorwp_get_automation_actions( $automation->id );

    ?>
    <?php // Section title and subtitle ?>
    <div class="automatorwp-title"><?php _e( 'Actions', 'automatorwp' ); ?></div>
    <div class="automatorwp-subtitle"><?php _e( 'Do this...', 'automatorwp' ); ?></div>

    <?php // Actions ?>
    <div class="automatorwp-automation-items automatorwp-actions">

        <?php $actions = automatorwp_check_automation_required_actions( $automation, $actions ); ?>

        <?php foreach( $actions as $action ) : ?>

            <?php automatorwp_automation_item_edit_html( $action, 'action', $automation ); ?>

        <?php endforeach; ?>

    </div>

    <?php automatorwp_automation_ui_add_item_form( $automation, 'action' ); ?>

    <?php // Add Action ?>
    <button type="button" class="button automatorwp-button-success automatorwp-add-action"><span class="dashicons dashicons-plus"></span><?php _e( 'Add Action', 'automatorwp' ); ?></button>
    <?php // Add Filter ?>
    <button type="button" class="button button-primary automatorwp-add-filter"><span class="dashicons dashicons-filter"></span><?php _e( 'Add Filter', 'automatorwp' ); ?></button>
    <?php // Box spinner ?>
    <div class="automatorwp-spinner automatorwp-box-spinner" style="display: none;">
        <span class="spinner is-active"></span>
        <span class="spinner-label"><?php _e( 'Saving...', 'automatorwp' ); ?></span>
    </div>
    <?php
}

/**
 * Automation UI add item form
 *
 * @since 1.0.0
 *
 * @param stdClass  $automation The automation object
 * @param string    $item_type  The item type (trigger|action)
 */
function automatorwp_automation_ui_add_item_form( $automation, $item_type ) {

    $choices_filters = array(
        'show_in_selector' => true,
    );

    if( $item_type === 'trigger' ) {
        $choices_filters['anonymous'] = (bool) ( $automation->type === 'anonymous' );
    }

    // Sort integrations
    $integrations = AutomatorWP()->integrations;
    ksort( $integrations );

    ?>

    <div class="automatorwp-add-item-form" style="display: none;">

        <div class="automatorwp-automation-item-details">
            <div class="automatorwp-integration-icon"></div>
        </div>

        <div class="automatorwp-automation-item-content">

            <?php
            /**
             * Available action at top of the add item content
             *
             * @since 1.57
             *
             * @param stdClass  $automation         The automation object
             * @param string    $item_type          The item type
             */
            do_action( 'automatorwp_automation_ui_add_item_content_top', $automation, $item_type ); ?>

            <div class="automatorwp-automation-item-actions">
                <div class="automatorwp-automation-item-action automatorwp-automation-item-action-close" title="<?php echo esc_attr( __( 'Close', 'automatorwp') ); ?>"><span class="dashicons dashicons-no-alt"></span></div>
            </div>

            <div class="automatorwp-select-integration automatorwp-form">

                <div class="automatorwp-select-integration-label"><?php _e( 'Select an integration', 'automatorwp' ); ?></div>

                <select class="automatorwp-all-integrations-choices">
                    <option value=""><?php echo esc_html( $item_type === 'trigger' ? __( 'Search for triggers', 'automatorwp' ) : __( 'Search for actions', 'automatorwp' ) ); ?></option>
                    <?php foreach( $integrations as $integration => $args ) : ?>

                        <?php // Skip filters
                        if( $integration === 'filter' ) continue; ?>

                        <?php switch ( $item_type ) {
                            case 'trigger':
                                $choices = automatorwp_get_integration_triggers( $integration, $choices_filters );
                                break;
                            case 'action':
                                $choices = automatorwp_get_integration_actions( $integration, $choices_filters );
                                break;
                            default:
                                $choices = array();
                                break;
                        }

                        // Skip integrations without triggers or actions
                        if( ! empty( $choices ) ) : ?>
                            <optgroup label="<?php echo esc_attr( $args['label'] ); ?>" data-icon="<?php echo esc_attr( $args['icon'] ); ?>">

                            <?php foreach( $choices as $trigger => $args ) :

                                if( empty( $args['select_option'] ) && empty( $args['label'] ) ) {
                                    continue;
                                } ?>
                                <option value="<?php echo esc_attr( $trigger ); ?>" data-text="<?php echo esc_attr( $args['select_option'] ); ?>"><?php echo $args['label']; ?></option>
                            <?php endforeach; ?>

                            </optgroup>

                        <?php endif; ?>

                    <?php endforeach; ?>
                </select>

                <div class="automatorwp-integrations">

                    <?php foreach( $integrations as $integration => $args ) : ?>

                        <?php // Skip filters
                        if( $integration === 'filter' ) continue; ?>

                        <?php switch ( $item_type ) {
                            case 'trigger':
                                $choices = automatorwp_get_integration_triggers( $integration, $choices_filters );
                                break;
                            case 'action':
                                $choices = automatorwp_get_integration_actions( $integration, $choices_filters );
                                break;
                            default:
                                $choices = array();
                                break;
                        }

                        // Skip integrations without triggers or actions
                        if( ! empty( $choices ) ) : ?>

                            <div class="automatorwp-integration"
                                 data-integration="<?php echo esc_attr( $integration ); ?>"
                                 data-label="<?php echo esc_attr( $args['label'] ); ?>"
                                 data-icon="<?php echo esc_attr( $args['icon'] ); ?>">
                                <div class="automatorwp-integration-icon">
                                    <img src="<?php echo esc_attr( $args['icon'] ); ?>" alt="<?php echo esc_attr( $args['label'] ); ?>">
                                </div>
                                <div class="automatorwp-integration-label"><?php echo $args['label']; ?></div>
                            </div>

                        <?php endif; ?>

                        <?php
                        /**
                         * Available action to extend integration markup
                         *
                         * @since 1.0.0
                         *
                         * @param string    $integration        The integration name
                         * @param array     $integration_args   Integration arguments
                         * @param stdClass  $automation         The automation object
                         * @param string    $item_type          The item type
                         */
                        do_action( 'automatorwp_automation_ui_after_integration_choice', $integration, $args, $automation, $item_type ); ?>

                    <?php endforeach; ?>

                </div>

            </div>

            <div class="automatorwp-integration-choices-container" style="display: none;">

                <?php if ( $item_type === 'trigger' ) : ?>

                    <div class="automatorwp-select-trigger-label"><?php _e( 'Select a trigger', 'automatorwp' ); ?></div>

                    <?php foreach( $integrations as $integration => $args ) : ?>

                        <?php // Skip filters
                        if( $integration === 'filter' ) continue; ?>

                        <select class="automatorwp-integration-choices"
                                data-integration="<?php echo esc_attr( $integration ); ?>"
                                data-placeholder="<?php echo esc_attr( __( 'Search for triggers', 'automatorwp' ) ); ?>"
                                style="display: none;">

                                <option value=""></option>
                            <?php foreach( automatorwp_get_integration_triggers( $integration, $choices_filters ) as $trigger => $args ) :

                                if( empty( $args['select_option'] ) && empty( $args['label'] ) ) {
                                    continue;
                                } ?>
                                <option value="<?php echo esc_attr( $trigger ); ?>" data-text="<?php echo esc_attr( $args['select_option'] ); ?>"><?php echo $args['label']; ?></option>
                            <?php endforeach; ?>

                            <?php
                            /**
                             * Available action to extend integration triggers choices
                             *
                             * @since 1.2.4
                             *
                             * @param string    $integration        The integration name
                             * @param array     $integration_args   Integration arguments
                             * @param stdClass  $automation         The automation object
                             * @param string    $item_type          The item type
                             */
                            do_action( 'automatorwp_automation_ui_after_integration_triggers_choices', $integration, $args, $automation, $item_type ); ?>

                        </select>

                    <?php endforeach; ?>

                <?php elseif ( $item_type === 'action' ) : ?>

                    <div class="automatorwp-select-action-label"><?php _e( 'Select an action', 'automatorwp' ); ?></div>

                    <?php foreach( $integrations as $integration => $args ) : ?>

                        <select class="automatorwp-integration-choices"
                                data-integration="<?php echo esc_attr( $integration ); ?>"
                                data-placeholder="<?php echo esc_attr( __( 'Search for actions', 'automatorwp' ) ); ?>"
                                style="display: none;">

                            <option value=""></option>
                            <?php foreach( automatorwp_get_integration_actions( $integration, $choices_filters ) as $action => $args ) :

                                if( empty( $args['select_option'] ) && empty( $args['label'] ) ) {
                                    continue;
                                } ?>
                                <option value="<?php echo esc_attr( $action ); ?>" data-text="<?php echo esc_attr( $args['select_option'] ); ?>"><?php echo $args['label']; ?></option>
                            <?php endforeach; ?>

                            <?php
                            /**
                             * Available action to extend integration actions choices
                             *
                             * @since 1.2.4
                             *
                             * @param string    $integration        The integration name
                             * @param array     $integration_args   Integration arguments
                             * @param stdClass  $automation         The automation object
                             * @param string    $item_type          The item type
                             */
                            do_action( 'automatorwp_automation_ui_after_integration_actions_choices', $integration, $args, $automation, $item_type ); ?>

                        </select>

                    <?php endforeach; ?>

                <?php endif; ?>

                <button type="button" class="button automatorwp-button-danger automatorwp-cancel-choice-select"><?php _e( 'Cancel', 'automatorwp' ); ?></button>

            </div>

            <?php
            /**
             * Available action at bottom of the add item content
             *
             * @since 1.57
             *
             * @param stdClass  $automation         The automation object
             * @param string    $item_type          The item type (trigger|action)
             */
            do_action( 'automatorwp_automation_ui_add_item_content_bottom', $automation, $item_type ); ?>

        </div>

    </div>

    <?php

}

/**
 * Get the object type args
 *
 * @since 1.0.0
 *
 * @param stdClass  $object     The trigger/action object
 * @param string    $item_type  The item type (trigger|action)
 *
 * @return array
 */
function automatorwp_automation_item_type_args( $object, $item_type ) {

    $type_args = array();

    if( $item_type === 'trigger' ) {
        $type_args = automatorwp_get_trigger( $object->type );
    } else if( $item_type === 'action' ) {
        $type_args = automatorwp_get_action( $object->type );
    }

    /**
     * Get the object type args
     *
     * @since 1.0.0
     *
     * @param array     $type_args  The trigger/action args
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     *
     * @return array
     */
    return apply_filters( 'automatorwp_automation_item_type_args', $type_args, $object, $item_type );

}

/**
 * Renders the trigger/action edit HTML
 *
 * @since  1.0.0
 *
 * @param stdClass  $object     The trigger/action object
 * @param string    $item_type  The item type (trigger|action)
 * @param stdClass  $automation The automation object
 */
function automatorwp_automation_item_edit_html( $object, $item_type, $automation ) {

    global $automatorwp_triggers_current_position;

    // Check item type
    if( ! in_array( $item_type, array( 'trigger', 'action' ) ) ) {
        return;
    }

    // Check type args
    $type_args = automatorwp_automation_item_type_args( $object, $item_type );

    if( ! $type_args ) {
        automatorwp_automation_missing_integration_item_edit_html( $object, $item_type, $automation );
        return;
    }

    // Check integration
    $integration = automatorwp_get_integration( $type_args['integration'] );

    if( ! $integration ) {
        automatorwp_automation_missing_integration_item_edit_html( $object, $item_type, $automation );
        return;
    }

    if( $item_type === 'action' && $object->type === 'automatorwp_anonymous_user' ) {
        $integration['icon'] = AUTOMATORWP_URL . 'assets/img/automatorwp-anonymous.svg';
    }

    // Setup the item classes
    $classes = array(
        'automatorwp-automation-item',
        'automatorwp-' . $item_type,
        'automatorwp-' . $item_type . '-' . str_replace( '_', '-', $object->type ),
    );

    if( $object->type === 'filter' ) {
        $classes[] = 'automatorwp-automation-item-filter';
    }

    // Setup the item actions
    $actions = array(
        'move-up' => array(
            'label' => __( 'Move up', 'automatorwp'),
            'icon' => 'arrow-up-alt2'
        ),
        'move-down' => array(
            'label' => __( 'Move down', 'automatorwp'),
            'icon' => 'arrow-down-alt2'
        ),
        'delete' => array(
            'label' => __( 'Delete', 'automatorwp'),
            'icon' => 'trash'
        ),
    );

    // Anonymous
    if( $automation->type === 'anonymous' ) {
        if( $item_type === 'trigger' ) {
            $classes[] = 'automatorwp-no-grab';
            unset( $actions['move-up'] );
            unset( $actions['move-down'] );
        } else if( $object->type === 'automatorwp_anonymous_user' ) {
            $classes[] = 'automatorwp-no-grab';
            unset( $actions['move-up'] );
            unset( $actions['move-down'] );
            unset( $actions['delete'] );
        }
    }

    /**
     * Filter to modify the integration args of the trigger/action edit HTML
     *
     * @since 1.0.0
     *
     * @param array     $integration The integration args
     * @param stdClass  $object The trigger/action object
     * @param string    $item_type The item type (trigger|action)
     * @param stdClass  $automation The automation object
     *
     * @return array
     */
    $integration = apply_filters( 'automatorwp_automation_item_edit_html_integration', $integration, $object, $item_type, $automation );

    /**
     * Filter to modify the CSS classes of the trigger/action edit HTML
     *
     * @since  1.3.0
     *
     * @param array     $classes    The trigger/action CSS classes
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     * @param stdClass  $automation The automation object
     *
     * @return array
     */
    $classes = apply_filters( 'automatorwp_automations_ui_item_edit_html_classes', $classes, $object, $item_type, $automation );

    /**
     * Filter to modify the actions of the trigger/action edit HTML
     *
     * @since  1.3.0
     *
     * @param array     $actions    The trigger/action actions
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     * @param stdClass  $automation The automation object
     *
     * @return array
     */
    $actions = apply_filters( 'automatorwp_automations_ui_item_edit_html_actions', $actions, $object, $item_type, $automation );

    ?>
    <div id="automatorwp-item-<?php echo esc_attr( $object->id ); ?>" class="<?php echo implode( ' ', $classes ); ?>">

        <div class="automatorwp-automation-item-details">
            <div class="automatorwp-integration-icon">
                <img src="<?php echo esc_attr( $integration['icon'] ); ?>" title="<?php echo esc_attr( $integration['label'] ); ?>" alt="<?php echo esc_attr( $integration['label'] ); ?>">
            </div>
        </div>

        <div class="automatorwp-automation-item-content">

            <?php if( ! empty( $actions ) ) : ?>
                <div class="automatorwp-automation-item-actions">
                    <?php foreach( $actions as $action => $action_args ) : ?>
                    <div class="automatorwp-automation-item-action automatorwp-automation-item-action-<?php echo $action; ?>" title="<?php echo esc_attr( $action_args['label'] ); ?>"><span class="dashicons dashicons-<?php echo $action_args['icon']; ?>"></span></div>
                    <?php endforeach; ?>

                </div>
            <?php endif; ?>

            <div class="automatorwp-integration-label"><?php echo $integration['label']; ?></div>

            <?php

            $position = ( is_int( $automatorwp_triggers_current_position ) ? $automatorwp_triggers_current_position + 1 : $object->position + 1 );

            if( $object->type !== 'filter' && is_int( $automatorwp_triggers_current_position ) ) {
                $automatorwp_triggers_current_position++;
            }

            ?>

            <div class="automatorwp-automation-item-position" style="<?php echo ( $automation->sequential ? '' : 'display: none;' ); ?>"><?php echo $position; ?>.</div>
            <div class="automatorwp-automation-item-label"><?php echo automatorwp_parse_automation_item_edit_label( $object, $item_type ); ?></div>

            <?php
            /**
             * After item label
             *
             * @since 1.0.0
             *
             * @param stdClass  $object     The trigger/action object
             * @param string    $item_type  The object type (trigger|action)
             */
            do_action( 'automatorwp_automation_ui_after_item_label', $object, $item_type ); ?>

            <?php // Render the options form ?>
            <?php foreach( $type_args['options'] as $option => $args ) : ?>

                <div class="automatorwp-option-form-container" data-option="<?php echo esc_attr( $option ); ?>" data-from="<?php echo esc_attr( ( isset( $args['from'] ) ? $args['from'] : '' ) ); ?>" style="display: none;">

                    <?php
                    /**
                     * After option from
                     *
                     * @since 1.0.0
                     *
                     * @param stdClass  $object     The trigger/action object
                     * @param string    $item_type  The object type (trigger|action)
                     * @param string    $option     The option key
                     * @param array     $args       The option arguments
                     */
                    do_action( 'automatorwp_automation_ui_after_option_form', $object, $item_type, $option, $args ); ?>

                    <?php
                    // Get the option form
                    $cmb2 = automatorwp_get_automation_item_option_form( $object, $item_type, $option, $automation );

                    if( $cmb2 ) {

                        ct_setup_table( "automatorwp_{$item_type}s" );

                        // Render the form
                        CMB2_Hookup::enqueue_cmb_css();
                        CMB2_Hookup::enqueue_cmb_js();
                        $cmb2->show_form();

                        ct_reset_setup_table();
                    }
                    ?>

                    <?php
                    /**
                     * Before option from
                     *
                     * @since 1.0.0
                     *
                     * @param stdClass  $object     The trigger/action object
                     * @param string    $item_type  The object type (trigger|action)
                     * @param string    $option     The option key
                     * @param array     $args       The option arguments
                     */
                    do_action( 'automatorwp_automation_ui_before_option_form', $object, $item_type, $option, $args ); ?>

                    <button type="button" class="button button-primary automatorwp-save-option-form"><?php _e( 'Save', 'automatorwp' ); ?></button>
                    <button type="button" class="button automatorwp-button-danger automatorwp-cancel-option-form"><?php _e( 'Cancel', 'automatorwp' ); ?></button>

                    <div class="automatorwp-spinner" style="display: none;">
                        <span class="spinner is-active"></span>
                        <span class="spinner-label"><?php _e( 'Saving...', 'automatorwp' ); ?></span>
                    </div>

                </div>

            <?php endforeach; ?>

        </div>

        <?php // Hidden fields ?>
        <input type="hidden" class="id" value="<?php echo esc_attr( $object->id ); ?>"/>
        <input type="hidden" class="type" value="<?php echo esc_attr( $object->type ); ?>"/>
        <input type="hidden" class="status" value="<?php echo esc_attr( $object->status ); ?>"/>
        <input type="hidden" class="position" value="<?php echo esc_attr( $object->position ); ?>"/>

    </div>
    <?php

}

/**
 * Creates if the required triggers exists
 *
 * @since  2.2.2
 *
 * @param stdClass  $automation The automation object
 * @param array     $triggers   The automation triggers
 *
 * @return array
 */
function automatorwp_check_automation_required_triggers( $automation, $triggers ) {

    return apply_filters( 'automatorwp_check_automation_required_triggers', $triggers, $automation );

}

/**
 * Creates if the required actions exists
 *
 * @since  1.3.0
 *
 * @param stdClass  $automation The automation object
 * @param array     $actions    The automation actions
 *
 * @return array
 */
function automatorwp_check_automation_required_actions( $automation, $actions ) {

    if( $automation->type === 'anonymous' ) {

        $create = false;

        // Check if the first action is the action required for anonymous automations
        if( ! isset( $actions[0] ) ) {
            $create = true;
        }

        if( isset( $actions[0] ) && $actions[0]->type !== 'automatorwp_anonymous_user' ) {
            $create = true;
        }

        if( $create ) {
            ct_setup_table( 'automatorwp_actions' );

            $action_data = array(
                'automation_id' => $automation->id,
                'title'         => sprintf( __( 'Actions will be run on %1$s', 'automatorwp' ), '{user}' ),
                'type'          => 'automatorwp_anonymous_user',
                'status'        => 'active',
                'position'      => '0',
                'date'          => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
            );

            // Insert the new action
            $action_id = ct_insert_object( $action_data );

            if( $action_id ) {
                $action_data['id'] = $action_id;

                $action_data = (object) $action_data;

                // Prepend the new action at start of the actions list
                array_unshift( $actions, $action_data );
            }

            ct_reset_setup_table();
        }

    }

    return apply_filters( 'automatorwp_check_automation_required_actions', $actions, $automation );

}

/**
 * Renders the trigger/action missing integration edit HTML
 *
 * @since  1.1.2
 *
 * @param stdClass  $object     The trigger/action object
 * @param string    $item_type  The item type (trigger|action)
 * @param stdClass  $automation The automation object
 */
function automatorwp_automation_missing_integration_item_edit_html( $object, $item_type, $automation ) {

    if( $item_type === 'trigger' ) {
        $warning_message = __( 'Trigger disabled because plugin associated couldn\'t be found. Please, re-install the plugin associated or remove this trigger.', 'automatorwp' );
    } else {
        $warning_message = __( 'Action disabled because plugin associated couldn\'t be found. Please, re-install the plugin associated or remove this action.', 'automatorwp' );

    }

    ?>
    <div id="automatorwp-item-<?php echo esc_attr( $object->id ); ?>" class="automatorwp-automation-item automatorwp-automation-missing-integration-item automatorwp-<?php echo esc_attr( $item_type ); ?>">

        <div class="automatorwp-automation-item-details">
            <div class="automatorwp-integration-icon">
                <img src="<?php echo esc_attr( AUTOMATORWP_URL . 'assets/img/integration-missing.svg' ); ?>" title="<?php echo esc_attr( __( 'Missing plugin', 'automatorwp' ) ); ?>">
            </div>
        </div>

        <div class="automatorwp-automation-item-content">

            <div class="automatorwp-automation-item-actions">
                <div class="automatorwp-automation-item-action automatorwp-automation-item-action-delete" title="<?php echo esc_attr( __( 'Delete', 'automatorwp') ); ?>"><span class="dashicons dashicons-trash"></span></div>
            </div>

            <div class="automatorwp-integration-label"><?php echo __( 'Missing plugin', 'automatorwp' ); ?></div>

            <div class="automatorwp-automation-item-position" style="<?php echo ( $automation->sequential ? '' : 'display: none;' ); ?>"><?php echo $object->position + 1; ?>.</div>
            <div class="automatorwp-automation-item-label"><?php echo $object->title; ?></div>

            <div class="automatorwp-notice-warning"><?php echo $warning_message; ?></div>

            <?php
            /**
             * After missing integration item label
             *
             * @since 1.1.2
             *
             * @param stdClass  $object     The trigger/action object
             * @param string    $item_type  The object type (trigger|action)
             */
            do_action( 'automatorwp_automation_ui_after_missing_integration_item_label', $object, $item_type ); ?>

        </div>

        <?php // Hidden fields ?>
        <input type="hidden" class="id" value="<?php echo esc_attr( $object->id ); ?>"/>
        <input type="hidden" class="type" value="<?php echo esc_attr( $object->type ); ?>"/>
        <input type="hidden" class="status" value="<?php echo esc_attr( $object->status ); ?>"/>
        <input type="hidden" class="position" value="<?php echo esc_attr( $object->position ); ?>"/>

    </div>
    <?php

}

/**
 * Parses the trigger/action edit label
 *
 * @since  1.0.0
 *
 * @param stdClass  $object     The trigger object
 * @param string    $item_type  The item type (trigger|action)
 * @param string    $context    The context this function is executed
 *
 * @return string
 */
function automatorwp_parse_automation_item_edit_label( $object, $item_type, $context = 'edit' ) {

    $type_args = automatorwp_automation_item_type_args( $object, $item_type );

    if( ! $type_args ) {
        return '';
    }

    /**
     * Filter to dynamically change the edit label
     *
     * @since 1.0.0
     *
     * @param string    $label      The edit label
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     * @param string    $context    The context this function is executed
     * @param array     $type_args  The type parameters
     *
     * @return string
     */
    $label = apply_filters( 'automatorwp_parse_automation_item_edit_label', $type_args['edit_label'], $object, $item_type, $context, $type_args );

    return automatorwp_parse_automation_item_label( $object, $item_type, $label, $context );

}

/**
 * Parses the trigger/action log label
 *
 * @since  1.0.0
 *
 * @param stdClass  $object     The trigger/action object
 * @param string    $item_type  The item type (trigger|action)
 * @param string    $context    The context this function is executed
 *
 * @return string
 */
function automatorwp_parse_automation_item_log_label( $object, $item_type, $context = 'edit' ) {

    $type_args = automatorwp_automation_item_type_args( $object, $item_type );

    if( ! $type_args ) {
        return '';
    }

    /**
     * Filter to dynamically change the log label
     *
     * @since 1.0.0
     *
     * @param string    $label      The edit label
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     * @param string    $context    The context this function is executed
     * @param array     $type_args  The type parameters
     *
     * @return string
     */
    $label = apply_filters( 'automatorwp_parse_automation_item_log_label', $type_args['log_label'], $object, $item_type, $context, $type_args );

    return automatorwp_parse_automation_item_label( $object, $item_type, $label, $context );

}

/**
 * Parses the trigger/action label given
 *
 * @since  1.0.0
 *
 * @param stdClass  $object     The trigger object
 * @param string    $item_type  The item type (trigger|action)
 * @param string    $label      The label to parse
 * @param string    $context    The context this function is executed
 *
 * @return string
 */
function automatorwp_parse_automation_item_label( $object, $item_type, $label, $context = 'edit' ) {

    $type_args = automatorwp_automation_item_type_args( $object, $item_type );

    if( ! $type_args ) {
        return '';
    }

    $replacements = array();

    foreach( $type_args['options'] as $option => $args ) {
        $replacements['{' . $option . '}'] = automatorwp_get_automation_item_option_replacement( $object, $item_type, $option, $context );
    }

    /**
     * Trigger/action label replacements
     *
     * @since 1.0.0
     *
     * @param array     $replacements   The replacements to apply
     * @param stdClass  $object         The trigger object
     * @param string    $item_type      The item type (trigger|action)
     * @param string    $label          The label to parse
     * @param string    $context        The context this function is executed
     *
     * @return array
     */
    $replacements = apply_filters( 'automatorwp_parse_automation_item_label_replacements', $replacements, $object, $item_type, $label, $context );

    $tags = array_keys( $replacements );

    $label_parsed = str_replace( $tags, $replacements, $label );
    
    /**
     * Trigger/action label parsed
     *
     * @since 1.0.0
     *
     * @param string    $label_parsed   The label parsed
     * @param stdClass  $object         The trigger object
     * @param string    $item_type      The item type (trigger|action)
     * @param string    $label          The originallabel to parse
     * @param string    $context        The context this function is executed
     * @param array     $tags           The tags applied
     * @param array     $replacements   The replacements applied
     *
     * @return string
     */
    return apply_filters( 'automatorwp_parse_automation_item_label', $label_parsed, $object, $item_type, $label, $context, $tags, $replacements );

}

/**
 * Get the option replacement
 *
 * @since 1.0.0
 *
 * @param stdClass  $object     The trigger/action object
 * @param string    $item_type  The item type (trigger|action)
 * @param string    $option     The option name
 * @param string    $context    The context this function is executed
 *
 * @return string
 */
function automatorwp_get_automation_item_option_replacement( $object, $item_type, $option, $context = 'edit' ) {

    global $automatorwp_event;

    // Check item type
    if( ! in_array( $item_type, array( 'trigger', 'action' ) ) ) {
        return false;
    }

    // Check type args
    $type_args = automatorwp_automation_item_type_args( $object, $item_type );

    if( ! $type_args ) {
        return '';
    }

    // Bail if this type hasn't any option
    if( ! isset( $type_args['options'][$option] ) ) {
        return '';
    }

    $option_args = $type_args['options'][$option];

    $field_id = ( isset( $option_args['from'] ) ? $option_args['from'] : '' );
    $value = '';

    // If not isset the from field, try to get a default value
    if( ! isset( $option_args['fields'][$field_id] ) ) {

        if( isset( $option_args['default'] ) && ! empty( $option_args['default'] ) ) {
            $value = $option_args['default'];
        }

    } else {

        ct_setup_table( "automatorwp_{$item_type}s" );
        
        $field = $option_args['fields'][$field_id];
        $value = ct_get_object_meta( $object->id, $field_id, true );
        
        if( ( $value === '' || is_null( $value ) ) && isset( $field['default'] ) ) {
            $value = $field['default'];
        }

        // Ensure the field value and escaped_value keys
        $field['object_id'] = $object->id;
        $field['value'] = $value;
        $field['escaped_value'] = $value;
        
        // Select field
        if( in_array( $field['type'], array( 'select', 'automatorwp_select', 'automatorwp_select_filter' ) ) ) {

            // Get the field options
            $field_options = automatorwp_get_field_options( $field );

            // Try to get the displayed value
            $found = automatorwp_get_array_key_value( $value, $field_options );

            if( $found ) {
                $value = $found;
            }
        }

        // Array values
        if( is_array( $value ) ) {

            // Get the field options
            $field_options = automatorwp_get_field_options( $field );

            // Replace values by the options label
            if( count( $field_options ) ) {
                foreach( $value as $i => $v ) {
                    // Try to get the displayed value
                    $found = automatorwp_get_array_key_value( $v, $field_options );

                    if( isset( $found ) ) {
                        $value[$i] = $found;
                    }
                }
            }

            /* translators: The ampersand character who represents the word "and" */
            $and = __( '&', 'automatorwp' );
            $value = automatorwp_implode_array( ', ', " {$and} ", $value );
        }

        // Fallback to default option if exists
        if( ( $value === '' || is_null( $value ) ) && isset( $option_args['default'] ) && ! empty( $option_args['default'] ) ) {
            $value = $option_args['default'];
        }

        ct_reset_setup_table();

    }

    /**
     * Filters the option value for replacement on labels
     *
     * @since 1.0.0
     *
     * @param string    $value      The option value
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     * @param string    $option     The option name
     * @param string    $context    The context this function is executed
     *
     * @return string
     */
    $value = apply_filters( 'automatorwp_get_automation_item_option_replacement', $value, $object, $item_type, $option, $context );

    if( $context === 'edit' ) {

        $option_class = 'button button-primary';

        if( $object->type === 'filter' ) {
            $option_class = 'button';
        }

        /**
         * Filters the option button class
         *
         * @since 1.2.4
         *
         * @param string    $option_class   The option class, by default "button button-primary"
         * @param stdClass  $object         The trigger/action object
         * @param string    $item_type      The item type (trigger|action)
         * @param string    $option         The option name
         * @param string    $context        The context this function is executed
         *
         * @return string
         */
        $option_class = apply_filters( 'automatorwp_get_automation_item_option_button_class', $option_class, $object, $item_type, $option, $context );

        $value = '<span class="' . esc_attr__( $option_class ) . ' automatorwp-option" data-option="' . $option . '">' . $value . '</span>';
    } else if( $context === 'view' ) {

        $automation = automatorwp_get_trigger_automation( $object->id );

        if( is_object( $automation ) ) {

            $user_id = ( isset( $automatorwp_event['user_id'] ) ? $automatorwp_event['user_id'] : 0 );

            $value = automatorwp_parse_automation_tags( $automation->id, $user_id, $value );
        }


    }

    return $value;

}

/**
 * Gets a CMB2 object from a trigger/action option
 *
 * @since 1.0.0
 *
 * @param stdClass  $object     The trigger/action object
 * @param string    $item_type  The item type (trigger|action)
 * @param string    $option     Option form to render
 * @param stdClass  $automation The automation object
 *
 * @return CMB2|false
 */
function automatorwp_get_automation_item_option_form( $object, $item_type, $option, $automation ) {

    // Check item type
    if( ! in_array( $item_type, array( 'trigger', 'action' ) ) ) {
        return false;
    }

    // Check type args
    $type_args = automatorwp_automation_item_type_args( $object, $item_type );

    if( ! $type_args ) {
        return false;
    }

    // Bail if this type hasn't any option
    if( ! isset( $type_args['options'][$option] ) ) {
        return false;
    }

    $args = $type_args['options'][$option];

    /**
     * Filter to override the trigger/action option fields
     *
     * @since 1.0.0
     *
     * @param array     $fields     The option fields
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     * @param string    $option     Option form to render
     * @param stdClass  $automation The automation object
     *
     * @return array
     */
    $fields = apply_filters( 'automatorwp_get_automation_item_option_form_fields', $args['fields'], $object, $item_type, $option, $automation );

    ct_setup_table( "automatorwp_{$item_type}s" );

    // Setup the CMB2 form
    $cmb2 = new CMB2( array(
        'id'        => $option .'_form',
        'object_types' => array( 'automatorwp_triggers', 'automatorwp_actions' ),
        'classes'   => 'automatorwp-form automatorwp-option-form',
        'hookup'    => false,
    ), $object->id );

    // Setup the options fields
    foreach ( $fields as $field_id => $field ) {

        $field['id'] = $field_id;

        if( $field['type'] === 'group' ) {
            // Group fields

            // Setup field arguments on each group field
            foreach ( $field['fields'] as $field_group_id => $field_group ) {

                $field_group['id'] = $field_group_id;

                $field['fields'][$field_group_id] = automatorwp_automation_item_option_field_args( $object, $item_type, $option, $automation, $field_id . '[' .$field_group_id . ']', $field_group );

            }

        } else {
            // Single fields

            $field = automatorwp_automation_item_option_field_args( $object, $item_type, $option, $automation, $field_id, $field );

        }

        // Add the field to the form
        $cmb2->add_field( $field );

    }

    ct_reset_setup_table();

    return $cmb2;

}

/**
 * Gets a CMB2 object from a trigger option
 *
 * @since 1.0.0
 *
 * @param stdClass  $object     The trigger/action object
 * @param string    $item_type  The item type (trigger|action)
 * @param string    $option     Option form to render
 * @param stdClass  $automation The automation object
 * @param string    $field_id   The field ID
 * @param array     $field      The field parameters
 *
 * @return array
 */
function automatorwp_automation_item_option_field_args( $object, $item_type, $option, $automation, $field_id, $field ) {

    $repeatable = ( isset( $field['repeatable'] ) && $field['repeatable'] === true );

    // Prevent to render field names to avoid conflicts on the main form
    $field['attributes']['name'] = '';

    // Update id attribute to avoid id collisions
    $field['attributes']['id'] = $field_id . '-' . $object->id;
    $field['attributes']['data-option'] = $field_id . ( $repeatable ? '[]' : '' );

    // Setup the fields tags selector

    // Set a specific sanitization callback for fields that support HTML and URLs
    if( in_array( $field['type'], array( 'textarea', 'wysiwyg', 'oembed', 'file' ) ) ) {
        $field['sanitization_cb'] = 'automatorwp_textarea_sanitization_cb';
    }

    // Check if field type is compatible with tags selector
    if( in_array( $field['type'], array( 'text', 'textarea', 'wysiwyg', 'file' ) ) ) {
        $field['after_field'] = automatorwp_get_tags_selector_html( $automation, $object, $item_type );
    }

    // If field is required, update its label with the required mark
    if( isset( $field['required'] ) && $field['required'] && isset( $field['name'] ) ) {
        $field['name'] .= '<span class="automatorwp-field-required">*</span>';
    }

    /**
     * Filter available to process custom field parameters
     *
     * @since 1.0.0
     *
     * @param array     $field      The field parameters
     * @param stdClass  $object     The trigger/action object
     * @param string    $item_type  The item type (trigger|action)
     * @param string    $option     Option form to render
     * @param stdClass  $automation The automation object
     * @param string    $field_id   The field ID
     *
     * @return array
     */
    return apply_filters( 'automatorwp_automation_item_option_field_args', $field, $object, $item_type, $option, $automation, $field_id );

}