<?php

namespace IGD_PRO;

// Exit if accessed directly.
use IGD\App;
use IGD\Uploader;

defined( 'ABSPATH' ) || exit;

\GFForms::include_addon_framework();

class GravityForms extends \GFAddOn {

    protected $_version = '2.0';
    protected $_min_gravityforms_version = '2.5';
    protected $_slug = 'integrate_google_drive';
    protected $_path = IGD_INCLUDES . '/integrations/class-gravityforms.php';
    protected $_full_path = __FILE__;
    protected $_title = 'Google Drive Add-On for GravityForms';
    protected $_short_title = 'Google Drive Add-On';

    public function init() {
        parent::init();

        if ( ! $this->is_gravityforms_supported( $this->_min_gravityforms_version ) ) {
            return;
        }

        // Add default value for field
        add_action( 'gform_editor_js_set_default_values', [ $this, 'field_defaults' ] );

        // Add a custom setting to the field
        add_action( 'gform_field_standard_settings', [ $this, 'custom_field_settings' ], 10, 2 );

        // Filter to add the tooltip for the field
        add_filter( 'gform_tooltips', [ $this, 'add_tooltip' ] );

        // Add support for wpDataTables <> Gravity Form integration
        if ( class_exists( 'WPDataTable' ) ) {
            add_action( 'wpdatatables_before_get_table_metadata', [ $this, 'render_wpdatatables_field' ], 10, 1 );
        }

        // Deprecated hooks, but still in use by e.g. GravityView + GravityFlow?
        add_filter( 'gform_entry_field_value', [ $this, 'filter_entry_field_value' ], 10, 4 );

        \GF_Fields::register( new GravityForms_Field() );

        //Preview scripts
        add_action( 'gform_preview_header', function () {
            \IGD\Enqueue::instance()->frontend_scripts();
        } );

        // Maybe create entry folder
        add_action( 'gform_after_submission', [ $this, 'may_create_entry_folder' ], 10, 2 );

        // Enqueue integration specific admin scripts
        add_filter( 'igd_should_enqueue_admin_scripts', [ $this, 'maybe_enqueue_admin_scripts' ], 10, 2 );

    }

    public function maybe_enqueue_admin_scripts( $should_enqueue, $hook ) {

        if ( 'toplevel_page_gf_edit_forms' === $hook ) {
            return true;
        }

        return $should_enqueue;
    }


    public function may_create_entry_folder( $entry, $form ) {
        $igd_fields = [];

        foreach ( $form['fields'] as $field ) {
            if ( $field->type == 'integrate_google_drive' ) {
                $igd_fields[] = $field;
            }
        }

        if ( ! empty( $igd_fields ) ) {
            foreach ( $igd_fields as $field ) {
                $value = $entry[ $field->id ];

                if ( empty( $value ) ) {
                    continue;
                }

                $files = json_decode( $value, true );

                if ( empty( $files ) ) {
                    continue;
                }

                $shortcode_data = \IGD\Shortcode::get_shortcode_data( $field->module_id );

                $tag_data = [
                        'form' => [
                                'form_title' => $form['title'],
                                'form_id'    => $form['id'],
                                'entry_id'   => $entry['id'],
                        ]
                ];

                // Rename files
                $file_name_template = ! empty( $shortcode_data['uploadFileName'] ) ? $shortcode_data['uploadFileName'] : '%file_name%%file_extension%';

                // Check if the file name template contains dynamic tags
                if ( igd_contains_tags( 'field', $file_name_template ) ) {

                    // Get dynamic tags by filtering the form data
                    $extra_tags = $this->handle_form_field_tags( $file_name_template, $form['fields'], $entry );

                    $rename_files = [];
                    foreach ( $files as $file ) {
                        // We will rename the file name
                        $tag_data['name'] = $file['name'];

                        $name = igd_replace_template_tags( $tag_data, $extra_tags );

                        $rename_files[] = [
                                'id'   => $file['id'],
                                'name' => $name,
                        ];
                    }

                    // Rename files
                    if ( ! empty( $rename_files ) ) {
                        App::instance()->rename_files( $rename_files );
                    }

                }

                // Check and create entry folder
                $create_entry_folder   = ! empty( $shortcode_data['createEntryFolders'] );
                $create_private_folder = ! empty( $shortcode_data['createPrivateFolder'] );

                if ( ! $create_entry_folder && ! $create_private_folder ) {
                    continue;
                }

                $entry_folder_name_template = ! empty( $shortcode_data['entryFolderNameTemplate'] ) ? $shortcode_data['entryFolderNameTemplate'] : 'Entry (%entry_id%) - %form_title%';

                if ( igd_contains_tags( 'user', $entry_folder_name_template ) ) {
                    if ( $entry['created_by'] ) {
                        $tag_data['user'] = get_userdata( $entry['created_by'] );
                    }
                }

                if ( igd_contains_tags( 'post', $entry_folder_name_template ) ) {
                    $referrer = wp_get_referer();

                    if ( ! empty( $referrer ) ) {
                        $post_id = url_to_postid( $referrer );
                        if ( ! empty( $post_id ) ) {
                            $tag_data['post'] = get_post( $post_id );
                            if ( $tag_data['post']->post_type == 'product' ) {
                                $tag_data['wc_product'] = wc_get_product( $post_id );
                            }
                        }
                    }
                }

                // Dynamic tags
                $extra_tags = [];
                if ( igd_contains_tags( 'field', $entry_folder_name_template ) ) {
                    $extra_tags = $this->handle_form_field_tags( $entry_folder_name_template, $form['fields'], $entry );
                }

                $tag_data['name'] = $entry_folder_name_template;
                $folder_name      = igd_replace_template_tags( $tag_data, $extra_tags );

                Uploader::instance()->create_entry_folder_and_move( $files, $folder_name, $shortcode_data );
            }
        }
    }

    private function handle_form_field_tags( $name_template, $form_fields, $entry ) {

        $extra_tags = [];

        // get %field_{key}% from the file name template
        preg_match_all( '/%field_id_([^%]+)%/', $name_template, $matches );
        $field_ids = $matches[1];

        if ( ! empty( $field_ids ) ) {
            foreach ( $form_fields as $tagField ) {
                $field_id = $tagField->id;

                if ( ! in_array( $field_id, $field_ids ) ) {
                    continue;
                }

                if ( empty( $entry[ $tagField->id ] ) ) {
                    // implode all items of the array that key starts with $tagField->id. (with a dot)
                    $field_value = '';

                    foreach ( $entry as $key => $value ) {
                        if ( ! empty( $value ) && strpos( $key, $tagField->id . '.' ) === 0 ) {
                            $field_value .= $value . ' ';
                        }
                    }

                } else {
                    $field_value = $entry[ $tagField->id ];
                }


                // Handle array values, such as checkboxes
                if ( is_array( $field_value ) ) {
                    $field_value = implode( ', ', $field_value );
                }

                $extra_tags[ '%field_id_' . $field_id . '%' ] = $field_value;
            }

        }

        return $extra_tags;
    }

    public function custom_field_settings( $position, $form_id ) {
        if ( 1430 == $position ) {

            $shortcodes = \IGD\Shortcode::get_shortcodes();

            $shortcodes = array_filter( $shortcodes, function ( $shortcode ) {
                return 'browser' === $shortcode['type'] || 'uploader' === $shortcode['type'];
            } );

            $options = "<option value=''>" . esc_html__( 'Select Module', 'integrate-google-drive-premium' ) . "</option>";

            if ( ! empty( $shortcodes ) ) {
                foreach ( $shortcodes as $shortcode ) {
                    $options .= sprintf(
                            "<option value='%s'>%s</option>",
                            esc_attr( $shortcode['id'] ),
                            esc_html( $shortcode['title'] )
                    );
                }
            }

            ?>
            <li class="igd_settings field_setting">
                <label for="field_module_id_<?php echo esc_attr( $this->_slug ); ?>"><?php esc_html_e( 'Select Module', 'integrate-google-drive-premium' ); ?><?php echo gform_tooltip( 'form_field_' . $this->_slug ); ?></label>

                <select
                        id="field_module_id_<?php echo esc_attr( $this->_slug ); ?>"
                        class="igd-uploader-data" onchange="SetFieldProperty('module_id', this.value)">
                    <?php echo $options; ?>
                </select>

                <button id="igd-form-uploader-config-gravityforms"
                        type="button"
                        class="igd-form-uploader-trigger igd-btn btn-primary"
                >
                    <i class="dashicons dashicons-admin-generic"></i>
                    <span><?php esc_html_e( 'Configure', 'integrate-google-drive-premium' ); ?></span>
                </button>

            </li>
            <?php
        }
    }

    public function add_tooltip( $tooltips ) {
        $tooltips[ 'form_field_' . $this->_slug ] = esc_html__( 'Enter the existing module id or create a new module.', 'integrate-google-drive-premium' );

        return $tooltips;
    }

    public function field_defaults() {
        ?>
        case 'integrate_google_drive':
        field.label = <?php echo json_encode( esc_html__( 'Attach your documents', 'integrate-google-drive-premium' ) ); ?>;
        break;
        <?php
    }

    public function render_wpdatatables_field( $tableId ) {
        add_filter( 'gform_get_input_value', [ $this, 'entry_field_value' ], 10, 4 );
    }

    public function filter_entry_field_value( $value, $field, $entry, $form ) {
        return $this->entry_field_value( $value, $entry, $field, null );
    }

    public function entry_field_value( $value, $entry, $field, $input_id ) {
        if ( 'integrate_google_drive' !== $field->type ) {
            return $value;
        }

        return apply_filters( 'igd_render_form_field_data', html_entity_decode( $value ), true, $this );
    }
}

class GravityForms_Field extends \GF_Field {
    public $type = 'integrate_google_drive';
    public $defaultValue = '';

    public function get_form_editor_field_title() {
        return __( 'Google Drive', 'integrate-google-drive-premium' );
    }

    public function add_button( $field_groups ) {
        $field_groups = $this->maybe_add_field_group( $field_groups );

        return parent::add_button( $field_groups );
    }

    public function maybe_add_field_group( $field_groups ) {
        foreach ( $field_groups as $field_group ) {
            if ( 'igd_group' == $field_group['name'] ) {
                return $field_groups;
            }
        }

        $field_groups[] = [
                'name'   => 'igd_group',
                'label'  => __( 'Integrate Google Drive Fields', 'integrate-google-drive-premium' ),
                'fields' => [],
        ];

        return $field_groups;
    }

    public function get_form_editor_button() {
        return [
                'group' => 'igd_group',
                'text'  => $this->get_form_editor_field_title(),
        ];
    }

    public function get_form_editor_field_icon() {
        return 'gform-icon--upload';
    }

    public function get_form_editor_field_description() {
        return esc_attr__( 'Let users attach files to this form. The files will be stored in the Google Drive', 'integrate-google-drive-premium' );
    }

    public function get_form_editor_field_settings() {
        return [
                'conditional_logic_field_setting',
                'error_message_setting',
                'label_setting',
                'label_placement_setting',
                'admin_label_setting',
                'rules_setting',
                'visibility_setting',
                'duplicate_setting',
                'description_setting',
                'css_class_setting',
                'igd_settings',
        ];
    }

    public function get_value_default() {
        return $this->is_form_editor() ? $this->defaultValue : \GFCommon::replace_variables_prepopulate( $this->defaultValue );
    }

    public function is_conditional_logic_supported() {
        return false;
    }

    public function get_field_input( $form, $value = '', $entry = null ) {
        $form_id         = $form['id'];
        $is_entry_detail = $this->is_entry_detail();
        $id              = $this->id;

        if ( $is_entry_detail ) {
            $input = "<input type='hidden' id='input_{$id}' name='input_{$id}' value='{$value}' />";

            return $input . '<br/>' . esc_html__( 'This field is not editable', 'integrate-google-drive-premium' );
        }

        $shortcode_data = \IGD\Shortcode::get_shortcode( $this->module_id )['config'] ?? [];;

        $default_data = [
                'type'           => 'uploader',
                'isFormUploader' => 'gravityforms',
                'isRequired'     => ! empty( $this->isRequired ),
                'uploadedFiles'  => ! empty( $value ) ? json_decode( $value, 1 ) : [],
        ];

        $data = wp_parse_args( $shortcode_data, $default_data );

        if ( $this->is_multi_page_form( $form ) ) {
            $data['uploadImmediately'] = true;
        }

        $input = \IGD\Shortcode::instance()->render_shortcode( '', $data );

        $input .= "<input type='text' name='input_" . $id . "' id='input_" . $form_id . '_' . $id . "'  class='upload-file-list igd-hidden' value='" . $value . "'>";

        return sprintf( '<div class="gform-theme__disable">%s</div>', $input );
    }

    public function is_multi_page_form( $form ) {
        $is_multi_page = false;

        foreach ( $form['fields'] as $field ) {
            if ( $field->type == 'page' ) {
                $is_multi_page = true;
                break;
            }
        }

        return $is_multi_page;
    }

    public function validate( $value, $form ) {

        // Get information uploaded files from hidden input
        $attached_files = json_decode( $value );

        if ( empty( $attached_files ) && $this->isRequired ) {
            $this->failed_validation = true;

            if ( ! empty( $this->errorMessage ) ) {
                $this->validation_message = $this->errorMessage;
            } else {
                $this->validation_message = esc_html__( 'This field is required. Please upload your files.', 'integrate-google-drive-premium' );
            }
        }

        //Check minimum files
        $shortcode_data = \IGD\Shortcode::get_shortcode( $this->module_id )['config'] ?? [];

        if ( ! empty( $shortcode_data['minFiles'] ) && ( empty( $attached_files ) || count( $attached_files ) < $shortcode_data['minFiles'] ) ) {
            $this->failed_validation = true;

            if ( ! empty( $this->errorMessage ) ) {
                $this->validation_message = $this->errorMessage;
            } else {
                $this->validation_message = sprintf( esc_html__( 'Please upload at least %d files.', 'integrate-google-drive-premium' ), $shortcode_data['minFiles'] );
            }
        }

    }

    public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
        return $this->render_uploaded_files( html_entity_decode( $value ), ( 'html' === $format ) );
    }

    public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) {
        return $this->render_uploaded_files( html_entity_decode( $value ), ( 'html' === $format ) );
    }

    public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
        if ( ! empty( $value ) ) {
            return $this->render_uploaded_files( html_entity_decode( $value ) );
        }
    }

    public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
        $value = rgar( $entry, $input_id );

        return $this->render_uploaded_files( html_entity_decode( $value ), false );
    }

    public function render_uploaded_files( $data, $as_html = true ) {
        return apply_filters( 'igd_render_form_field_data', $data, $as_html, $this );
    }

    public function get_field_container_tag( $form ) {
        if ( \GFCommon::is_legacy_markup_enabled( $form ) ) {
            return parent::get_field_container_tag( $form );
        }

        return 'fieldset';
    }

}

new GravityForms();
