Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
108 kB
7
Indexable
<?php

/*
 * Plugin Name: Zen Agency - Fancy Product Designer Customization
 * Plugin URI: https://zen.agency/
 * Description: Fancy Product Designer Customizations.
 * Version: 1.0
 * Author: Zen Agency
 * Author URI: https://zen.agency/
 * Copyright: (c) 2021 Zen Agency
 * License: GNU General Public License v2.0
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: zen-agency-fpd
 */
ini_set('display_errors', 1);

if (!defined('ABSPATH'))
    exit; // Exit if accessed directly

use Filestack\FilestackClient;
use Filestack\FilestackSecurity;
use Filestack\Filelink;
use Filestack\FilestackException;

class ZenFancyProductDesigner {

    const ADVANCED_CUSTOM_FIELDS = 'advanced-custom-fields/acf.php';
    const FANCY_PRODUCT_DESIGNER = 'fancy-product-designer/fancy-product-designer.php';
    const CART_ITEM_ZEN_FPD_KEY = 'zenFpd';
    const ZEN_FPD_IMPORT_FOLDER = 'zen_fpd_imports';
    const ZEN_FPD_ORDER_ITEM_META = '_zen_fpd_data';
    const ADVANCED_CUSTOM_FIELDS_SLUG = 'zen-fpd-settings';
    const ADVANCED_CUSTOM_FIELDS_TEXT_REG_EX = '/[^A-Za-z0-9 ]/';
    const ADVANCED_CUSTOM_FIELDS_STRIP_SPACES_REG_EX = '/[\s]/';
    const ADVANCED_CUSTOM_FIELDS_COLOR_HEX_REG_EX = '/[^A-Za-z0-9#]/';
    const PRINTAVO_CUSTOMER_ID_META_KEY = 'printavo-customer-id';
    const PRINTAVO_ORDER_ID_META_KEY = '_printavo_order_id';
    const PRINTAVO_STAGING_API_EMAIL = 'tara@zen.agency';
    const PRINTAVO_STAGING_API_TOKEN = 'SpmIlgW4KoPMZUD0RV5RMA';
    const PRINTAVO_STAGING = false;
    const PRINTAVO_DEV = false;

    protected static $instance;
    private $plugin_version = '1.0';
    private $plugin_directory = '';
    private $plugin_basename = '';
    private $plugin_path = '';
    private $plugin_url = '';
    private $lang_json = '';
    private $templates_directory = '';
    private $force_cache_buster = true;
    private $active_plugins = array();
    private $acf_fields = array(
        'fpd_locations' => 'fpd_location_name',
        'fpd_views' => 'fpd_view_name',
        'fpd_sizes' => 'fpd_size',
        'fpd_color_images' => 'fpd_views',
        'fpd_number_of_colors' => 'fpd_number_of_colors',
        'product_page_dimensions_labels' => 'label'
    );
    private $upload_directory = '';
    private $upload_directory_uri = '';
    private $fpd_design_query = '';
    private $fpd_design_query_variable_name = '';
    private $fpd_design_query_swatch_selected = '';
    private $printavo_advanced_custom_fields = array(
        'printavo_api_url',
        'printavo_api_email',
        'printavo_api_token',
        'printavo_invoice_url',
        'printavo_default_invoice_status_id',
        'printavo_default_customer_order_due_date_interval'
    );
    private $printavo_api_url = '';
    private $printavo_api_email = '';
    private $printavo_api_token = '';
    private $printavo_invoice_url = '';
    private $printavo_default_invoice_status_id = '';
    private $printavo_default_customer_order_due_date_interval = 1;
    private $printavo_uri_params = array();
    private $states = array();
    private $filestack_settings = array(
        'filestack_api_token'
    );
    private $filestack_client = null;
    private $filestack_api_token = '';
    private $filestack_security = null;
    private $filestack_security_token = '';

    public static function instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function __construct() {
        $v = get_file_data(__FILE__, array('Version' => 'Version'), 'plugin');

        $this->plugin_version = $v['Version'];
        $this->plugin_path = dirname(__FILE__);
        $this->plugin_url = plugin_dir_url(__FILE__);
        $this->plugin_directory = plugin_dir_path(__FILE__);
        $this->plugin_basename = plugin_basename(__FILE__);

        $this->templates_directory = plugins_url('/fancy-product-designer/html/', __FILE__);
        $this->lang_json = plugins_url('/fancy-product-designer/lang/default.json', __FILE__);

        $this->active_plugins = get_option('active_plugins');

        if ($this->force_cache_buster) {
            $this->plugin_version = $this->plugin_version . '_' . time();
        }

        $upload_dir = wp_upload_dir();
        $this->upload_directory = sprintf('%s/%s/%s/', $upload_dir['basedir'], self::ZEN_FPD_IMPORT_FOLDER, '%s');
        $this->upload_directory_uri = sprintf('%s/%s/%s/', $upload_dir['baseurl'], self::ZEN_FPD_IMPORT_FOLDER, '%s');

        add_action('init', array($this, 'init'));
        add_action('wp', array($this, 'wpInit'));

        $this->initPrintavoSettings();

        $this->initFileStackSettings();

        $this->initAuthCookiesActions();

        $this->initWooCommerceOrderActionsAndFilters();

        $this->initWooCommerceProfileActionsAndFilters();

        $this->initWooCommerceSaveForLaterActions();

        $this->initMetaBoxActions();

        if (is_admin() && $this->advancedCustomFieldsIsValid()) {
            add_action('acf/validate_save_post', array($this, 'advancedCustomFieldsValidateFields'));
            add_filter('acf/load_field/name=fpd_views_by_locations', array($this, 'loadOptionsViewsByLocationsFieldChoices'));
            add_filter('acf/load_field/name=fpd_location_pricing', array($this, 'loadOptionsLocationPricingFieldChoices'));
            add_filter('acf/load_field/name=fpd_tool_tip_display', array($this, 'loadOptionsToolTipDisplayFieldChoices'));
            add_filter('acf/load_field/name=fpd_sizes', array($this, 'loadProductAvailableSizesChoices'));
            add_filter('acf/load_field/name=fpd_views', array($this, 'loadProductAvailableViewsChoices'));
            add_filter('acf/load_field/name=fpd_color_images', array($this, 'loadProductAvailableViewsChoices'));
            add_filter('acf/load_field/name=product_page_dimensions_labels', array($this, 'loadProductDimensionsLabels'));
            add_filter('acf/update_value', array($this, 'updateAdvancedCustomFieldValues'), 10, 4);
            add_filter('mce_buttons_2', array($this, 'advancedCustomFieldsTinyMceButtons'), 10, 2);
            add_filter('teeny_mce_buttons', array($this, 'advancedCustomFieldsTinyMceTeenyButtons'), 10, 2);
            add_filter('mce_external_plugins', array($this, 'advancedCustomFieldsTinyMcePlugins'));
        }

        $this->fpd_design_query_variable_name = 'zen_fpd_saved_design';
        $this->fpd_design_query = filter_input(INPUT_GET, $this->fpd_design_query_variable_name, FILTER_SANITIZE_STRING);
        if (empty($this->fpd_design_query)) {
            $this->fpd_design_query_variable_name = 'zen_fpd_cart_item';
            $this->fpd_design_query = filter_input(INPUT_GET, $this->fpd_design_query_variable_name, FILTER_SANITIZE_STRING);
        }
        $this->fpd_design_query_swatch_selected = filter_input(INPUT_GET, 'zen_fpd_swatch_color', FILTER_SANITIZE_STRING);
        $states = @include WC()->plugin_path() . '/i18n/states.php';
        if (!empty($states) && is_array($states)) {
            $this->states = $states;
        }

        require_once $this->plugin_path . '/vendor/autoload.php';
        $filestack_sdk = $this->getAllFiles($this->plugin_path . DIRECTORY_SEPARATOR . 'filestack', true);
        rsort($filestack_sdk); // mixins need to be first
        foreach ($filestack_sdk as $filestack) {
            require_once $filestack;
        }
    }

    public function init() {
        $this->initAdminAdvancedCustomFieldsSettings();
        add_rewrite_endpoint('saved-designs', EP_ROOT | EP_PAGES);
        add_filter('plugin_action_links_' . $this->plugin_basename, array($this, 'pluginActionLinks'));
    }

    public function wpInit() {
        if ($this->fancyProductDesignerIsValid() && $this->advancedCustomFieldsIsValid()) {
            $this->enqueueStoreFrontStylesAndScripts();
            $this->addStoreFrontActionsAndFilters();
        }
        $this->updateCartItem();
        $this->deleteSavedDesign();

        // TESTING
//        $this->printRFormatted($this->printavoUser());
//        $this->printavoOrderCreate(null, 10828);
//        $upload_dir = sprintf($this->upload_directory, '8dec87430c67b645611cd524ab63db18');
//        foreach ($this->getAllFiles($upload_dir) as $file) {
//            $this->printRFormatted(array('Filename' => 9418 . '_' . basename($file)));
//        };
//        $this->filestackClientInit();
//        $this->printRFormatted($this->filestackUploadApi(
//                        sprintf($this->upload_directory, '35305bd373c15eef8a8ea02336a51e3b') . 'Back.png'
//        ));
//        $this->printavoOrderStatuses();
//        $this->printavoSetCustomer(5);
//        $this->printavoSearchCustomer('tech@zendesignfirm.com');
//        $this->printavoSearchCustomer('john@doe.com');
//        $order = wc_get_order(9442);
//        $this->printRFormatted($order->get_address());
//        $this->printRFormatted($order->get_address('shipping'));
    }

    public function pluginActionLinks($actions) {
        $custom_actions = array();
        if ($this->advancedCustomFieldsIsValid()) {
            $custom_actions[] = '<a href="' . esc_url(get_admin_url(null, 'admin.php?page=' . self::ADVANCED_CUSTOM_FIELDS_SLUG)) . '">Zen Agency Settings</a>';
        }
        if ($this->fancyProductDesignerIsValid()) {
            $custom_actions[] = '<a href="' . esc_url(get_admin_url(null, 'admin.php?page=fancy_product_designer')) . '">Fancy Product Designer</a>';
        }
        return array_merge($custom_actions, $actions);
    }

    public function initMetaBoxActions() {
        add_action('fpd_post_meta_box_end', array($this, 'fancyProductDesignAdminMetaBox'));
        add_action('do_meta_boxes', array($this, 'doMetaBoxes'));
    }

    public function initAuthCookiesActions() {
        add_action('set_auth_cookie', array($this, 'setAuthCookie'), 10, 5);
        add_action('clear_auth_cookie', array($this, 'clearAuthCookie'), 10, 5);
    }

    public function initWooCommerceSaveForLaterActions() {
        add_action('wp_ajax_zen_fpd_save_design', array($this, 'saveDesign'));
        add_action('wp_ajax_nopriv_zen_fpd_save_design', array($this, 'saveDesign'));
        add_action('wp_ajax_zen_fpd_saved_design', array($this, 'loadSavedDesign'));
        add_action('wp_ajax_nopriv_zen_fpd_process_login', array($this, 'processLogin'));
    }

    public function initWooCommerceProfileActionsAndFilters() {
        add_action('show_user_profile', array($this, 'addCustomerMetaFields'));
        add_action('edit_user_profile', array($this, 'addCustomerMetaFields'));
        add_action('personal_options_update', array($this, 'saveCustomerMetaFields'));
        add_action('edit_user_profile_update', array($this, 'saveCustomerMetaFields'));
    }

    public function initWooCommerceOrderActionsAndFilters() {
        // Add to cart
        add_filter('woocommerce_add_cart_item', array($this, 'addCartItem'), 10, 1);

        // Add item data to the cart
        add_filter('woocommerce_add_cart_item_data', array($this, 'addCartItemData'), 10, 2);
        add_filter('woocommerce_get_item_data', array($this, 'getItemData'), 10, 2);

        // Unique cart item id
//        add_filter('woocommerce_cart_id', array($this, 'cartId'), 10, 5);
        // Load cart data per page load
        add_filter('woocommerce_get_cart_item_from_session', array($this, 'getCartItemFromSession'), 10, 3);

        // display total quantity (all sizes)
        add_filter('woocommerce_cart_item_quantity', array($this, 'cartItemQuantity'), 10, 3);
        add_filter('woocommerce_checkout_cart_item_quantity', array($this, 'checkoutCartItemQuantity'), 10, 3);
        add_filter('woocommerce_order_item_quantity_html', array($this, 'orderItemQuantityHtml'), 10, 3);

        // Remove abilty to "undo" item removal
        add_filter('woocommerce_cart_item_removed_notice_type', function() {
            return 'zen_fpd';
        });
        add_filter('woocommerce_add_zen_fpd', function($message) {
            return '';
        });

        // Order Again
        add_filter('woocommerce_valid_order_statuses_for_order_again', array($this, 'validOrderStatusesForOrderAgain'));
        // add_filter('woocommerce_order_again_cart_item_data', array($this, 'orderAgainCartItemData'), 10, 3);
        // Cart Link
        add_filter('woocommerce_cart_item_permalink', array($this, 'cartItemPermalink'), 10, 3);

        // View Orders Item Count 
        add_filter('woocommerce_get_item_count', array($this, 'getItemCount'), 10, 3);

        // Mini Cart Product Args
        add_filter('xoo_wsc_cart_body_args', array($this, 'miniCartProduct'), 10, 1);

        // Load FPD cart item on product page
        add_action('wp_ajax_zen_fpd_cart_item', array($this, 'loadFancyProductCartItem'));
        add_action('wp_ajax_nopriv_zen_fpd_cart_item', array($this, 'loadFancyProductCartItem'));

        // Add meta to order
        add_action('woocommerce_new_order_item', array($this, 'orderItemMeta'), 10, 3);

        // Delete folder and all images when removed
        add_action('woocommerce_cart_item_removed', array($this, 'cartItemRemoved'));

        add_action('woocommerce_before_order_itemmeta', array($this, 'adminOrderItemValues'), 10, 3);
        add_action('woocommerce_order_item_meta_start', array($this, 'orderItemMetaStart'), 10, 3);

        // Mini Cart Edit Design
        add_action('xoo_wsc_product_summary_col_end', array($this, 'miniCartProductSummaryColEnd'), 10, 2);

        // Restore item/images
        // add_action('woocommerce_cart_item_restored', array($this, 'cartItemRestored'));
        // Validate when adding to cart
        // add_filter('woocommerce_add_to_cart_validation', array($this, 'addToCartValidation'), 10, 3);
        // add_filter('save_post', array($this, 'printavoOrderUpdate'), 10, 2);
        add_filter('woocommerce_payment_successful_result', array($this, 'printavoOrderCreate'), 10, 2);
        add_filter('woocommerce_order_item_needs_processing', array($this, 'orderItemNeedsProcessing'), 10, 3);

        // ups shipping
        add_filter('woocommerce_cart_shipping_packages', array($this, 'cartShippingPackages'));
    }

    public function cartShippingPackages($packages) {
        foreach ($packages as $package_key => $package) {
            foreach ($package['contents'] as $item_id => $values) {
                if (is_array($values[self::CART_ITEM_ZEN_FPD_KEY]['size'])) {
                    $packages[$package_key]['contents'][$item_id]['quantity'] = array_sum($values[self::CART_ITEM_ZEN_FPD_KEY]['size']);
                }
            }
        }
        return $packages;
    }

    public function doMetaBoxes() {
        // remove fpd plugin from shop order and only show zen fpd data
        if ($this->fancyProductDesignerIsValid() && $this->advancedCustomFieldsIsValid()) {
            remove_meta_box(
                    'fpd-order', 'shop_order', 'normal'
            );
        }
    }

    public function enqueueStoreFrontStylesAndScripts() {
        global $post;
        if (is_account_page()) {
            wp_enqueue_script('zen-agency-fpd-account-scripts', plugins_url('/js/account-scripts.js', __FILE__), array(), $this->plugin_version, true);
        }
        if (is_a($post, 'WP_Post') && is_fancy_product($post->ID)) {
            wp_enqueue_style('zen-agency-fpd-main-style', plugins_url('/fancy-product-designer/css/main.css', __FILE__), array(), $this->plugin_version);
//            wp_enqueue_style('zen-agency-fpd-all', plugins_url('/fancy-product-designer/css/FancyProductDesigner-all.min.css', __FILE__), array(), $this->plugin_version);
//            wp_enqueue_style('zen-agency-fpd-zen-style', plugins_url('/css/styles.css', __FILE__), array(), $this->plugin_version . '_' . time());
            wp_register_script('zen-agency-fpd-scripts', plugins_url('/js/scripts.js', __FILE__), array(), $this->plugin_version, true);
            wp_register_script('zen-agency-fpd-jquery-ui', plugins_url('/fancy-product-designer/js/jquery-ui.min.js', __FILE__), array(), $this->plugin_version, true);
            wp_register_script('zen-agency-fpd-fabric-min', plugins_url('/fancy-product-designer/js/fabric.min.js', __FILE__), array(), $this->plugin_version, true);
            wp_register_script('zen-agency-fpd-all', plugins_url('/fancy-product-designer/js/FancyProductDesigner-all.min.js', __FILE__), array(), $this->plugin_version, true);
            wp_register_script('zen-agency-fpd', plugins_url('/fancy-product-designer/js/FancyProductDesignerPlus.min.js', __FILE__), array(), $this->plugin_version, true);
        }
        if (is_account_page() || is_shop() || (is_a($post, 'WP_Post') && is_fancy_product($post->ID))) {
            wp_enqueue_style('zen-agency-fpd-zen-style', plugins_url('/css/styles.css', __FILE__), array(), $this->plugin_version . '_' . time());
            // FPD comes with tooltipster... however, it doesn't work correctly... Leave here just in case
//            wp_enqueue_style('zen-agency-fpd-tooltipster', plugins_url('/css/tooltipster.bundle.min.css', __FILE__), array(), $this->plugin_version . '_' . time());
//            wp_enqueue_script('zen-agency-fpd-tooltipster', plugins_url('/js/tooltipster.bundle.min.js', __FILE__), array(), $this->plugin_version, true);
        }
        if ((!is_user_logged_in() && (is_a($post, 'WP_Post') && is_fancy_product($post->ID))) ||
                (is_user_logged_in() && is_account_page())) {
            wp_enqueue_style('zen-agency-fpd-jquery-fancybox', plugins_url('/css/jquery.fancybox.min.css', __FILE__), array(), $this->plugin_version . '_' . time());
            wp_enqueue_script('zen-agency-fpd-jquery-fancybox', plugins_url('/js/jquery.fancybox.min.js', __FILE__), array(), $this->plugin_version, true);
        }
    }

    public function addStoreFrontActionsAndFilters() {
        global $post;
        if (is_shop()) {
            add_filter('body_class', function($classes) {
                $classes[] = 'zen-fpd-shop-page';
                return $classes;
            }, 10);
        }
        if (is_a($post, 'WP_Post') && is_fancy_product($post->ID)) {
            $fpd_design_query = $this->fpd_design_query;
            $fpd_design_query_variable_name = $this->fpd_design_query_variable_name;
            remove_action('woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30);
            remove_action('woocommerce_simple_add_to_cart', 'woocommerce_simple_add_to_cart', 30);
            remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_title', 5);
            remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_price', 10);

            add_action('woocommerce_before_single_product', function() {
                remove_action('woocommerce_before_single_product_summary', 'FPD_Frontend_Product::add_product_designer', 15);
                add_action('woocommerce_before_single_product_summary', function() {
                    $this->productPageTitle('mobile');
                }, 10);
                add_action('woocommerce_before_single_product_summary', array($this, 'productPageViewer'), 15);
                add_action('wp_footer', array($this, 'footerInit'), 11);
            }, 1);
            add_action('woocommerce_single_product_summary', function() {
                $this->productPageTitle('desktop');
            }, 5);
            add_action('woocommerce_single_product_summary', array($this, 'productPageTeamMemberQuote'), 10);
            add_action('woocommerce_variable_add_to_cart', function() use ($post, $fpd_design_query, $fpd_design_query_variable_name) {
                $this->productPageIncludes($post, $fpd_design_query, $fpd_design_query_variable_name);
            }, 30);
            add_action('woocommerce_simple_add_to_cart', function() use ($post, $fpd_design_query, $fpd_design_query_variable_name) {
                $this->productPageIncludes($post, $fpd_design_query, $fpd_design_query_variable_name);
            }, 30);
            add_action('woocommerce_before_add_to_cart_form', function() {
                echo '<style>.fpf-fields-config-wrapper{display: none;}</style>';
            });
            add_action('woocommerce_before_single_product_summary', array($this, 'outputProductWrapper'), 0);
            add_action('woocommerce_after_single_product_summary', array($this, 'outputProductWrapperEnd'), 0);

            add_filter('body_class', function($classes) {
                $classes[] = 'zen-fpd-page';
                return $classes;
            }, 10);
            //add_filter('woocommerce_product_tabs', array($this, 'productTabs'));
            remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_rating', 10);

            add_action('woocommerce_before_main_content', array($this, 'productPageBeforeMainContent'), 1);
            add_action('woocommerce_after_main_content', array($this, 'productPageAfterMainContent'), 11);
        }
        add_filter('woocommerce_account_menu_items', array($this, 'accountMenuItems'), 10, 2);
        add_action('woocommerce_account_saved-designs_endpoint', array($this, 'loadAccountSavedDesigns'));
        add_filter('woocommerce_get_price_html', array($this, 'shopPagePrice'), 10, 2);
        add_action('pp_woo_products_title_after', array($this, 'shopPageSwatches'));
        remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
    }

    public function productPageViewer() {
        @include 'views/fpd-product-page-viewer.php';
    }

    public function productPageIncludes($post, $fpd_design_query, $fpd_design_query_variable_name) {
        @include 'views/fpd-product-page-accordion-tabs.php';
        @include 'views/fpd-product-page-add-to-cart.php';
    }

    /*public function productPageDetails() {
        @include 'views/fpd-product-page-details.php';
    }*/

    public function productPageTeamMemberQuote() {
        @include 'views/fpd-product-page-team-member-quote.php';
    }

    public function productPageTitle($view) {
        @include 'views/fpd-product-page-title.php';
    }

    public function addCustomerMetaFields($user) {
        @include 'views/admin-profile-fields.php';
    }

    public function productPageBeforeMainContent() {
        echo '<div id="zen-main-content">';
    }

    public function productPageAfterMainContent() {
        echo '</div>';
    }

    public function saveCustomerMetaFields($user) {
        $this->updateUserMeta($user, self::PRINTAVO_CUSTOMER_ID_META_KEY, $_POST[self::PRINTAVO_CUSTOMER_ID_META_KEY]);
    }

    public function shopPagePrice($price, $clazz) {
        if ($this->advancedCustomFieldsIsValid() && method_exists($clazz, 'get_id')) {
            $base_price = get_field('base_price', $clazz->get_id());
            if (!empty($base_price) && is_numeric($base_price)) {
                $price = wc_price($base_price) . ((method_exists($clazz, 'get_price_suffix')) ? $clazz->get_price_suffix() : '');
            }
        }
        return $price;
    }

    public function shopPageSwatches() {
        @include 'views/fpd-shop-page-swatches.php';
    }
  /*  public function productTabs($tabs) {
        unset($tabs['additional_information']);
        $tabs['details'] = array(
            'title' => 'Details',
            'priority' => 20,
            'callback' => array($this, 'productPageDetails')
        );
        $tabs['related_products'] = array(
            'title' => 'Related Products',
            'priority' => 40,
            'callback' => 'woocommerce_output_related_products'
        );
        $tabs['reviews']['title'] = 'Ratings &amp; Reviews';
//        $this->printRFormatted($tabs);
        return $tabs;
    }*/

    public function advancedCustomFieldsValidateFields() {
        global $post;
        if (current_user_can('manage_options')) {
            acf_reset_validation_errors();
        }
        if (!empty($_POST['acf'])) {
//            if (is_a($post, 'WP_Post') && 'product' == $post->post_type) {
//                $colors = get_field_object('fpd_colors', $post->ID);
//                if (!empty($colors) &&
//                        is_array($colors) &&
//                        !empty($colors['key']) &&
//                        !empty($colors['sub_fields']) &&
//                        is_array($colors['sub_fields'])
//                ) {
//                    $color_key = '';
//                    $color_name_key = '';
//                    foreach ($colors['sub_fields'] as $sub_field) {
//                        if ('fpd_color' == $sub_field['name']) {
//                            $color_key = $sub_field['key'];
//                        }
//                        if ('fpd_color_name' == $sub_field['name']) {
//                            $color_name_key = $sub_field['key'];
//                        }
//                    }
//                    if (!empty($color_key) || !empty($color_name_key)) {
//                        foreach ($_POST['acf'][$colors['key']] as $row => $color) {
//                            if (!empty($color_key)) {
//                                $_POST['acf'][$colors['key']][$row][$color_key] = trim(preg_replace(self::ADVANCED_CUSTOM_FIELDS_COLOR_HEX_REG_EX, ' ', sanitize_text_field($color[$color_key])));
//                            }
//                            if (!empty($color_name_key)) {
//                                $_POST['acf'][$colors['key']][$row][$color_name_key] = trim(preg_replace(self::ADVANCED_CUSTOM_FIELDS_TEXT_REG_EX, ' ', sanitize_text_field($color[$color_name_key])));
//                            }
//                        }
//                    }
//                    if (array_filter(
//                                    array_count_values(
//                                            array_map(function($v) {
//                                                return strtolower($v);
//                                            }, array_column($_POST['acf'][$colors['key']], $color_key)
//                                            )
//                                    ), function($count) {
//                                return $count > 1;
//                            })) {
//                        $_POST['acf'][$colors['key']] = array_unique($_POST['acf'][$colors['key']], SORT_REGULAR);
//                    }
//                }
//            }
            if (!empty($_POST['_acf_screen']) && 'options' == $_POST['_acf_screen']) {
                $locations = get_field_object('fpd_locations', 'options');
                $this->advancedCustomFieldsValidateInput($locations, 'fpd_location_name');

                $views = get_field_object('fpd_views', 'options');
                $this->advancedCustomFieldsValidateInput($views, 'fpd_view_name');

                $sizes = get_field_object('fpd_sizes', 'options');
                $this->advancedCustomFieldsValidateInput($sizes, 'fpd_size');

                $tool_tip_display = get_field_object('fpd_tool_tip_display', 'options');
                $this->advancedCustomFieldsValidateInput($tool_tip_display, 'fpd_locations', false);

                $views_by_locations = get_field_object('fpd_views_by_locations', 'options');
                $this->advancedCustomFieldsValidateInput($views_by_locations, 'fpd_locations', false);

                $product_page_dimensions_labels = get_field_object('product_page_dimensions_labels', 'options');
                $this->advancedCustomFieldsValidateInput($product_page_dimensions_labels, 'label', false);

                $location_pricing = get_field_object('fpd_location_pricing', 'options');
                if (!empty($_POST['acf'][$location_pricing['key']]) && is_array($_POST['acf'][$location_pricing['key']])) {
                    $_POST['acf'][$location_pricing['key']] = array_unique($_POST['acf'][$location_pricing['key']], SORT_REGULAR);
                }
            }
        }
    }

    public function advancedCustomFieldsTinyMcePlugins($plugins) {
        $table_plugin = '/js/tinymce/plugins/table/plugin.min.js';
        if (is_array($plugins) && file_exists(untrailingslashit($this->plugin_directory) . $table_plugin)) {
            $plugins['table'] = plugins_url($table_plugin, __FILE__);
        }
        return $plugins;
    }

    public function advancedCustomFieldsTinyMceButtons($mce_buttons, $editor_id) {
        if (is_array($mce_buttons)) {
            array_unshift($mce_buttons, 'table');
        }
        return $mce_buttons;
    }

    public function advancedCustomFieldsTinyMceTeenyButtons($mce_buttons, $editor_id) {
        if (is_array($mce_buttons)) {
            $mce_buttons[] = 'table';
        }
        return $mce_buttons;
    }

    public function accountMenuItems($items, $endpoints) {
        $items = array_slice($items, 0, count($items) - 1, true) +
                array('saved-designs' => 'Saved designs') +
                array_slice($items, count($items) - 1, null, true);
        return $items;
    }

    public function loadAccountSavedDesigns() {
        $saved_designs = array();
        $user_meta = get_user_meta(get_current_user_id());
        if (!empty($user_meta) && is_array($user_meta)) {
            $saved_designs = array_filter($user_meta, function($v) use($user_meta) {
                return preg_match('#saved_design_#', array_search($v, $user_meta));
            });
            if (!empty($saved_designs) && is_array($saved_designs)) {
                foreach ($saved_designs as $design_key => $design) {
                    $saved_designs[$design_key]['key'] = $design_key;
                    $saved_designs[$design_key]['design'] = $design[0];
                    unset($saved_designs[$design_key][0]);
                }
                $saved_designs = array_values($saved_designs);
                krsort($saved_designs);
            }
        }
        wc_get_template('account-saved-designs.php', array('saved_designs' => $saved_designs), 'zen-fancy-product-designer/', $this->plugin_directory . '/views/');
    }

    public function loadSavedDesign() {
        $current_user_id = get_current_user_id();
        $saved_design = sanitize_text_field($_POST['zen_fpd_design']);
        if (!empty($current_user_id) && !empty($saved_design)) {
            $user_meta = get_user_meta($current_user_id, $saved_design, true);
            if (!empty($user_meta)) {
                wp_die(json_encode($user_meta));
            }
        }
        wp_die(json_encode(array()));
    }

    public function loadFancyProductCartItem() {
        $cart = WC()->cart->get_cart();
        $cart_item = sanitize_text_field($_POST['zen_fpd_design']);
        if (!empty($cart) &&
                !empty($cart_item) &&
                is_array($cart) &&
                !empty($cart[$cart_item]) &&
                !empty($cart[$cart_item][self::CART_ITEM_ZEN_FPD_KEY])
        ) {
            $product_options = array();
            foreach ($cart[$cart_item][self::CART_ITEM_ZEN_FPD_KEY] as $post_key => $post_value) {
                if (!in_array($post_key, array('shirt_artwork', 'add-to-cart', 'submit_design', 'product_data', 'product_id', 'action', 'product_id', 'total_price'))) {
                    $product_options[$post_key] = $post_value;
                }
            }
            wp_die(json_encode(array(
                self::CART_ITEM_ZEN_FPD_KEY => json_decode($cart[$cart_item][self::CART_ITEM_ZEN_FPD_KEY]['product_data']),
                'product_options' => $product_options
            )));
        }
        wp_die(json_encode(array()));
    }

    public function saveDesign() {
        $current_user_id = get_current_user_id();
        $result = array('success' => false);
        $this->sanitizeProductPostData();
        if (!empty($current_user_id) && $current_user_id == $_POST['user_id']) {
            $directory = ((!empty($_POST['update_saved_design'])) ? $_POST['update_saved_design'] : uniqid('saved_design_' . absint($_POST['product_id']) . '_' . $current_user_id . '_', true));
            $upload_dir = sprintf($this->upload_directory, $directory);
            $upload_dir_uri = sprintf($this->upload_directory_uri, $directory);
            $json_product_data = json_decode($_POST['product_data'], true);
            $product_options = array();
            foreach ($_POST as $post_key => $post_value) {
                if (!in_array($post_key, array('add-to-cart', 'product_data', 'product_id', 'action', 'product_id', 'total_price'))) {
                    $product_options[$post_key] = $post_value;
                }
            }
            if (!empty($_POST['update_saved_design'])) {
                $current_files = $this->getAllFiles($upload_dir, true);
                $current_files_names = array();
                if (!empty($current_files) && is_array($current_files)) {
                    foreach ($_POST['location'] as $location) {
                        $current_files_names[] = basename($location['existing_file']);
                    }
                    $current_files_names = array_filter($current_files_names);
                    foreach ($current_files as $current_file) {
                        if (!in_array(basename($current_file), $current_files_names)) {
                            $this->deleteImages($current_file, false);
                        }
                    }
                }
            }
            if (!empty($_FILES) && !empty($json_product_data) && is_array($json_product_data)) {
                if (!$this->uploadFiles($directory, $json_product_data)) {
                    $result['message'] = 'Failed to save uploaded images, please try again.';
                    wp_die(json_encode($result));
                }
            }
            if (!empty($_POST['update_cart'])) {
                if (!file_exists($upload_dir) && !wp_mkdir_p($upload_dir)) {
                    $result['message'] = 'Failed to create saved files, please try again.';
                    wp_die(json_encode($result));
                }
                if (empty($result['message'])) {
                    foreach ($_POST['location'] as $location) {
                        if (!empty($location['existing_file'])) {
                            $existing_file_name = basename($location['existing_file']);
                            $parse_url = parse_url($location['existing_file']);
                            if (!empty($parse_url) &&
                                    is_array($parse_url) &&
                                    !empty($parse_url['path'])
                            ) {
                                $explode = explode(self::ZEN_FPD_IMPORT_FOLDER, $parse_url['path']);
                                $relative_path = (!empty($explode[1])) ? $explode[1] : '';
                            }
                            if (!copy((!empty($relative_path) ? str_replace('/%s/', '', $this->upload_directory) . $relative_path : $location['existing_file']), $upload_dir . $existing_file_name)) {
                                $result['message'] = 'Failed to copy cart files, please try again.';
                                break;
                            }
                            if (!$this->findReplaceInArray($json_product_data, $location['existing_file'], $upload_dir_uri . $existing_file_name)) {
                                $result['message'] = 'Failed to save cart files, please try again.';
                                break;
                            }
                        }
                    }
                    if (!empty($result['message'])) {
                        $this->deleteImages($upload_dir);
                        wp_die(json_encode($result));
                    }
                    WC()->cart->remove_cart_item($_POST['update_cart']);
                    WC()->cart->set_session();
                }
            }
            $fpd_data = array(
                'title' => !empty($_POST['design_name']) ? $_POST['design_name'] : 'No Name',
                'product_id' => $_POST['product_id'],
                'product_options' => $product_options,
                'directory' => $directory,
                self::CART_ITEM_ZEN_FPD_KEY => $json_product_data
            );
            $update_user_meta = update_user_meta($current_user_id, $directory, $fpd_data);
            if (false === $update_user_meta) {
                $this->deleteImages($upload_dir);
                $result['message'] = 'Failed to save design, please try again.';
                wp_die(json_encode($result));
            }
            $result['success'] = true;
            $result['redirect'] = wc_get_endpoint_url('saved-designs', '', wc_get_page_permalink('myaccount'));
        }
        wp_die(json_encode($result));
    }

    public function processLogin() {
        $result = array('success' => false, 'message' => 'Credentials Required');
        $nonce_value = wc_get_var($_REQUEST['woocommerce-login-nonce'], wc_get_var($_REQUEST['_wpnonce'], '')); // @codingStandardsIgnoreLine.

        if (isset($_POST['username'], $_POST['password']) && wp_verify_nonce($nonce_value, 'woocommerce-login')) {

            try {
                $creds = array(
                    'user_login' => trim(wp_unslash($_POST['username'])), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
                    'user_password' => $_POST['password'], // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
                    'remember' => isset($_POST['rememberme']), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
                );

                $validation_error = new WP_Error();
                $validation_error = apply_filters('woocommerce_process_login_errors', $validation_error, $creds['user_login'], $creds['user_password']);

                if ($validation_error->get_error_code()) {
                    $result['message'] = $validation_error->get_error_message();
                    wp_die(json_encode($result));
                }

                if (empty($creds['user_login'])) {
                    $result['message'] = __('Username is required.', 'woocommerce');
                    wp_die(json_encode($result));
                }

                // Perform the login.
                $user = wp_signon($creds, is_ssl());

                if (is_wp_error($user)) {
                    $result['message'] = $user->get_error_message();
                    wp_die(json_encode($result));
                } else {
                    $result['message'] = '';
                    $result['user_id'] = $user->ID;
                    $result['success'] = true;
                    wp_die(json_encode($result));
                }
            } catch (Exception $e) {
                $result['message'] = $e->getMessage();
            }
        }
        wp_die(json_encode($result));
    }

    public function miniCartProductSummaryColEnd($product, $cart_item_key) {
        printf('<div class="zen-fpd-xoo-wsc-edit-design"><a href="%s">Edit Design</a></div>', add_query_arg('zen_fpd_cart_item', $cart_item_key, $product->get_permalink()));
    }

    public function miniCartProduct($args) {
        if (!empty($args['cart']) && is_array($args['cart'])) {
            foreach ($args['cart']as $cart_item_key => $cart_item) {
                if (isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY]) &&
                        !empty($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['size']) &&
                        is_array($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['size'])
                ) {
                    $args['cart'][$cart_item_key]['quantity'] = array_sum($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['size']);
                }
            }
        }
        return $args;
    }

    public function getItemCount($count, $item_type, $clazz) {
        $new_count = 0;
        foreach ($clazz->get_items() as $item) {
            $zen_fpd_data = $item->get_meta(self::ZEN_FPD_ORDER_ITEM_META);
            if (!empty($zen_fpd_data) && !empty($zen_fpd_data['size']) && is_array($zen_fpd_data['size'])) {
                $new_count += array_sum($zen_fpd_data['size']);
            }
        }
        return $new_count > 0 ? $new_count : $count;
    }

    public function cartItemPermalink($link, $cart_item, $cart_item_key) {
        if (isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY])) {
            $link = add_query_arg('zen_fpd_cart_item', $cart_item_key, $link);
        }
        return $link;
    }

    public function deleteSavedDesign() {
        $user_id = filter_input(INPUT_GET, 'user_id', FILTER_VALIDATE_INT);
        $delete = filter_input(INPUT_GET, 'delete', FILTER_SANITIZE_STRING);
        if (is_user_logged_in() && !empty($user_id) && !empty($delete)) {
            $current_user_id = get_current_user_id();
            if ($user_id == $current_user_id) {
                if (delete_user_meta($current_user_id, $delete)) {
                    $this->deleteImages(sprintf($this->upload_directory, $delete));
                }
            }
            wp_safe_redirect(remove_query_arg(array('delete', 'user_id'), wp_get_referer()));
            exit;
        }
    }

    public function updateCartItem() {
        if (!empty($_POST['update_cart'])) {
            $this->sanitizeProductPostData();
            $cart_contents = WC()->cart->get_cart_contents();
            $directory = $_POST['update_cart'];
            if (!empty($directory) && !empty($cart_contents[$directory])) {
                $current_files = $this->getAllFiles(sprintf($this->upload_directory, $directory), true);
                $current_files_names = array();
                if (!empty($current_files) && is_array($current_files)) {
                    foreach ($_POST['location'] as $location) {
                        $current_files_names[] = basename($location['existing_file']);
                    }
                    $current_files_names = array_filter($current_files_names);
                    foreach ($current_files as $current_file) {
                        if (!in_array(basename($current_file), $current_files_names)) {
                            $this->deleteImages($current_file, false);
                        }
                    }
                }
                $cart_contents[$_POST['update_cart']][self::CART_ITEM_ZEN_FPD_KEY] = $_POST;
                $this->saveImages($_POST['update_cart'], $cart_contents[$_POST['update_cart']][self::CART_ITEM_ZEN_FPD_KEY]);
                WC()->cart->set_cart_contents($cart_contents);
                WC()->cart->set_session();
                wp_safe_redirect(wc_get_cart_url());
                exit;
            }
        }
    }

    public function addCartItem($cart_item) {
        if (isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY])) {
            $cart_item['data']->set_price($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['total_price']);
            $cart_item['data']->set_name(
                    sprintf('<strong>%s</strong><p>%s</p>', $cart_item[self::CART_ITEM_ZEN_FPD_KEY]['design_name'], $cart_item['data']->get_name())
            );
            if (isset($_POST['submit_design']) && serialize($_POST) == serialize($cart_item[self::CART_ITEM_ZEN_FPD_KEY]) && empty($_POST['update_cart'])) {
                if (!$this->saveImages($cart_item['key'], $cart_item[self::CART_ITEM_ZEN_FPD_KEY])) {
                    throw new Exception('There was an error saving your artwork, please try again.');
                }
                $update_saved_design = !empty($_POST['update_saved_design']) ? $_POST['update_saved_design'] : '';
                if (is_user_logged_in() && !empty($update_saved_design)) {
                    $saved_design_dir = sprintf($this->upload_directory, $update_saved_design);
                    $upload_dir = sprintf($this->upload_directory, $cart_item['key']);
                    $upload_dir_uri = sprintf($this->upload_directory_uri, $cart_item['key']);
                    $json_product_data = json_decode($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['product_data'], true);
                    if (file_exists($saved_design_dir) &&
                            file_exists($upload_dir) &&
                            !empty($json_product_data) &&
                            is_array($json_product_data)
                    ) {
                        foreach ($_POST['location'] as $location) {
                            if (!empty($location['existing_file'])) {
                                $existing_file_name = basename($location['existing_file']);
                                $parse_url = parse_url($location['existing_file']);
                                if (!empty($parse_url) &&
                                        is_array($parse_url) &&
                                        !empty($parse_url['path'])
                                ) {
                                    $explode = explode(self::ZEN_FPD_IMPORT_FOLDER, $parse_url['path']);
                                    $relative_path = (!empty($explode[1])) ? $explode[1] : '';
                                }
                                if (!copy((!empty($relative_path) ? str_replace('/%s/', '', $this->upload_directory) . $relative_path : $location['existing_file']), $upload_dir . $existing_file_name)) {
                                    $result['message'] = 'Failed to copy cart files, please try again.';
                                    break;
                                }
                                if (!$this->findReplaceInArray($json_product_data, $location['existing_file'], $upload_dir_uri . $existing_file_name)) {
                                    $result['message'] = 'Failed to save cart files, please try again.';
                                    break;
                                }
                            }
                        }
                        if (!empty($result['message'])) {
                            $this->deleteImages($upload_dir);
                            throw new Exception($result['message']);
                        }
                        $cart_item[self::CART_ITEM_ZEN_FPD_KEY]['product_data'] = json_encode($json_product_data);
                        if (delete_user_meta(get_current_user_id(), $update_saved_design)) {
                            $this->deleteImages($saved_design_dir);
                        }
                    }
                }
            }
        }
        return $cart_item;
    }

    public function cartItemRemoved($cart_item_key) {
        if (!empty($cart_item_key)) {
            $this->deleteImages(sprintf($this->upload_directory, $cart_item_key));
        }
    }

    public function cartItemRestored($cart_item_key) {
        $cart_item = WC()->cart->get_cart_item($cart_item_key);
        if (isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY])) {
            $this->saveImages($cart_item_key, $cart_item[self::CART_ITEM_ZEN_FPD_KEY]);
        }
    }

    public function addCartItemData($cart_item_meta, $product_id) {
        if (isset($_POST['submit_design'])) {
            $this->sanitizeProductPostData();
            $cart_item_meta[self::CART_ITEM_ZEN_FPD_KEY] = $_POST;
        }
        return $cart_item_meta;
    }

    public function getCartItemFromSession($cart_item, $values, $key) {
        if (isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY])) {
            $this->addCartItem($cart_item);
        }
        return $cart_item;
    }

    public function cartItemQuantity($product_quantity, $cart_item_key, $cart_item) {
        if (isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY])) {
            $product_quantity = sprintf('%s <input type="hidden" name="cart[%s][qty]" value="1" />', !empty($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['size']) ? array_sum($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['size']) : '', $cart_item_key);
        }
        return $product_quantity;
    }

    public function checkoutCartItemQuantity($product_quantity, $cart_item, $cart_item_key) {
        if (isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY])) {
            $product_quantity = sprintf('<strong class="product-quantity">%s</strong>', !empty($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['size']) ? '&times;&nbsp;' . array_sum($cart_item[self::CART_ITEM_ZEN_FPD_KEY]['size']) : '1');
        }
        return $product_quantity;
    }

    public function orderItemQuantityHtml($product_quantity, $item) {
        $fpd_data = wc_get_order_item_meta($item->get_id(), self::ZEN_FPD_ORDER_ITEM_META);
        if (isset($fpd_data)) {
            $product_quantity = sprintf('<strong class="product-quantity">%s</strong>', !empty($fpd_data['size']) ? '&times;&nbsp;' . array_sum($fpd_data['size']) : '1');
        }
        return $product_quantity;
    }

    public function cartId($id_parts, $product_id, $variation_id, $variation, $cart_item_data) {
        if (isset($cart_item_data[self::CART_ITEM_ZEN_FPD_KEY])) {
            if (!$this->saveImages($id_parts, $cart_item_data[self::CART_ITEM_ZEN_FPD_KEY])) {
                throw new Exception('There was an error saving your artwork, please try again.');
            }
        }
        return $id_parts;
    }

    public function validOrderStatusesForOrderAgain() {
        return array();
    }

    public function orderAgainCartItemData($cart_item_data, $item, $order) {
        foreach ($item->get_meta_data() as $meta) {
            if ($meta->key === self::CART_ITEM_ZEN_FPD_KEY) {
                $cart_item_data[self::CART_ITEM_ZEN_FPD_KEY] = $meta->value;
            }
        }
        return $cart_item_data;
    }

    public function orderItemMeta($item_id, $item, $order_id) {
        $zenFpd = isset($item->legacy_values[self::CART_ITEM_ZEN_FPD_KEY]) ? $item->legacy_values[self::CART_ITEM_ZEN_FPD_KEY] : null;
        if (!is_null($zenFpd)) {
            $zenFpd['cart_item_key'] = $item->legacy_values['key'];
            wc_add_order_item_meta($item_id, self::ZEN_FPD_ORDER_ITEM_META, $zenFpd);
        }
    }

    public function getItemData($other_data, $cart_item) {
        $cart_item_zen_fpd = isset($cart_item[self::CART_ITEM_ZEN_FPD_KEY]) ? $cart_item[self::CART_ITEM_ZEN_FPD_KEY] : array();
        if (isset($cart_item_zen_fpd)) {
            foreach ($cart_item_zen_fpd as $key => $value) {
                switch ($key) {
                    case 'color':
                        $other_data[] = array('name' => 'Color', 'display' => $value, 'value' => $value, 'hidden' => false);
                        break;
                    case 'size':
                        foreach ($value as $size => $qty) {
                            if (is_numeric($qty)) {
                                $other_data[] = array('name' => $size, 'display' => $qty, 'value' => $qty, 'hidden' => false);
                            }
                        }
                        break;
                    case 'location':
                        foreach ($value as $location => $location_values) {
                            if (!empty($location_values['chosen']) &&
                                    !empty($location_values['number_ink_colors'])
                            ) {
                                $chosen_string = $location_values['chosen'];
                                if (!empty($location_values['choose_ink_styles'])) {
                                    $chosen_string .= ', Ink Style: ' . $location_values['choose_ink_styles'];
                                }
                                if (!empty($location_values['choose_width'])) {
                                    $chosen_string .= ', Width: ' . $location_values['choose_width'];
                                }
                                if (!empty($location_values['choose_height'])) {
                                    $chosen_string .= ', Height: ' . $location_values['choose_height'];
                                }
                                if (!empty($location_values['choose_notes'])) {
                                    $chosen_string .= ', Notes: ' . $location_values['choose_notes'];
                                }
                                $chosen_string .= ', # Ink Colors: ' . $location_values['number_ink_colors'];
                                $other_data[] = array('name' => $location, 'display' => $chosen_string, 'value' => $chosen_string, 'hidden' => false);
                            }
                        }
                        break;

                }
            }
        }
//        $this->printRFormatted($cart_item[self::CART_ITEM_ZEN_FPD_KEY]);
        return $other_data;
    }

    public function adminOrderItemValues($item_id, $item, $_product) {
        if (is_object($_product)) {
            $this->orderedItemMetaData($item_id);
        }
    }

    public function orderItemMetaStart($item_id, $item, $order) {
        $this->orderedItemMetaData($item_id);
    }

    public function footerInit() {
        global $post;
        if (is_a($post, 'WP_Post') && is_fancy_product($post->ID)) {
            $product_settings = new FPD_Product_Settings($post->ID);
            $fancy_content_ids = fpd_has_content($product_settings->master_id);
            $products_json_str = array();
            foreach ($fancy_content_ids as $fancy_content_id) {
                $fpd_product = new FPD_Product($fancy_content_id);
                $fpd_product_json = $fpd_product->to_JSON(false);
                if (!empty($fpd_product_json)) {
                    $products_json_str[] = $fpd_product_json;
                }
            }
            //output designs
            $designs_json_str = 'null';
            if (class_exists('FPD_Designs') &&
                    method_exists('FPD_Product_Settings', 'get_option') &&
                    method_exists('FPD_Product_Settings', 'get_image_parameters') &&
                    !intval($product_settings->get_option('hide_designs_tab'))
            ) {
                $fpd_designs = new FPD_Designs(
                        $product_settings->get_option('design_categories[]') ? $product_settings->get_option('design_categories[]') : array()
                        , $product_settings->get_image_parameters()
                );
                $designs_json_str = $fpd_designs->get_json();
            }
            $lang_json = $this->lang_json;
            $templates_directory = $this->templates_directory;
            $fpd_design_query = $this->fpd_design_query;
            $fpd_design_query_variable_name = $this->fpd_design_query_variable_name;
            $fpd_design_query_swatch_selected = $this->fpd_design_query_swatch_selected;
            $custom_image_params = "jQuery.extend(
                                        {},
                                        {$product_settings->get_custom_image_parameters_string()}
                                    )";
            wp_enqueue_script('zen-agency-fpd-scripts');
            wp_enqueue_script('zen-agency-fpd-jquery-ui');
            wp_enqueue_script('zen-agency-fpd-fabric-min');
            wp_enqueue_script('zen-agency-fpd-all');
            wp_enqueue_script('zen-agency-fpd');
            @include 'views/fpd-product-page-scripts.php';
        }
    }

    public function updateAdvancedCustomFieldValues($value, $post_id, $field, $original) {
        if (isset($_GET['page']) && self::ADVANCED_CUSTOM_FIELDS_SLUG == $_GET['page']) {
            if (!is_array($value) &&
                    !is_numeric($value) &&
                    'wysiwyg' != $field['type'] &&
                    !stristr($field['name'], 'printavo') &&
                    !stristr($field['name'], 'filestack') &&
                    !stristr($field['name'], 'label')
            ) {
                $value = trim(preg_replace(self::ADVANCED_CUSTOM_FIELDS_TEXT_REG_EX, ' ', sanitize_text_field($value)));
            }
            if ((stristr($field['name'], 'printavo') ||
                    stristr($field['name'], 'filestack')) &&
                    'text' != $field['type']
            ) {
                $value = trim(preg_replace(self::ADVANCED_CUSTOM_FIELDS_STRIP_SPACES_REG_EX, '', sanitize_text_field($value)));
            }
        }
        return $value;
    }

    public function loadProductAvailableViewsChoices($field) {
        global $post;
        if (is_a($post, 'WP_Post') && 'product' == $post->post_type) {
            $field = $this->addFieldsChoices($field);
        }
        return $field;
    }

    public function loadProductDimensionsLabels($field) {
        global $post;
        if (is_a($post, 'WP_Post') && 'product' == $post->post_type) {
            $field = $this->addFieldsChoices($field);
        }
        return $field;
    }

    public function loadProductAvailableSizesChoices($field) {
        global $post;
        if (is_a($post, 'WP_Post') && 'product' == $post->post_type) {
            $field = $this->addFieldsChoices($field);
        }
        return $field;
    }

    public function loadProductAvailableColorsViewsChoices($field) {
        global $post;
        if (isset($_GET['post']) && 'product' == $post->post_type) {
            $field = $this->addFieldsChoices($field, absint($_GET['post']));
        }
        return $field;
    }

    public function loadOptionsLocationPricingFieldChoices($field) {
        if (isset($_GET['page']) && self::ADVANCED_CUSTOM_FIELDS_SLUG == $_GET['page']) {
            $field = $this->addFieldsChoices($field);
        }
        return $field;
    }

    public function loadOptionsToolTipDisplayFieldChoices($field) {
        if (isset($_GET['page']) && self::ADVANCED_CUSTOM_FIELDS_SLUG == $_GET['page']) {
            $field = $this->addFieldsChoices($field);
        }
        return $field;
    }

    public function loadOptionsViewsByLocationsFieldChoices($field) {
        if (isset($_GET['page']) && self::ADVANCED_CUSTOM_FIELDS_SLUG == $_GET['page']) {
            $field = $this->addFieldsChoices($field);
        }
        return $field;
    }

    public function outputProductWrapper() {
        echo '<div id="zen-product-wrapper" class="display-flex">';
    }

    public function outputProductWrapperEnd() {
        echo '</div><!-- #end zen-product-wrapper -->';
    }

    public function fancyProductDesignAdminMetaBox() {
        printf('<script src="%s?%s" id="zen-agency-fpd-admin-scripts-js"></script>', plugins_url('/js/fpd-admin-scripts.js', __FILE__), $this->plugin_version);
    }

    public function printRFormatted($data = array(), $return = false, $var_dump = false) {
        if (!$return) {
            $print_formatted = '<pre>';
        }
        if (!$var_dump) {
            $print_formatted .= print_r($data, true);
        } else {
            if ($return) {
                $print_formatted .= var_export($data, true);
            } else {
                echo '<pre>';
                echo var_dump($data);
                echo '</pre>';
                return false;
            }
        }
        if (!$return) {
            $print_formatted .= '</pre>';
        }
        if ($return) {
            return $print_formatted;
        }
        echo $print_formatted;
    }

    public function setAuthCookie($auth_cookie, $expire, $expiration, $user_id, $scheme) {
        if (user_can($user_id, 'manage_woocommerce')) {
            setcookie('wordpress_logged_in_admin', 'SWuplUho6aT47FrAPo', $expire, SITECOOKIEPATH);
        }
    }

    public function clearAuthCookie($auth_cookie) {
        setcookie('wordpress_logged_in_admin', ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH);
    }

    public function displayDesignData($data, $echo = true) {
        if (!empty($data) && is_array($data)) {
            if (!$echo) {
                ob_start();
            }
            foreach ($data as $key => $value) {
                switch ($key) {
                    case 'color':
                        printf('<p><strong>Color:</strong>&nbsp;<span>%s</span></p>', $value);
                        break;
                    case 'size':
                        foreach ($value as $size => $qty) {
                            if (is_numeric($qty)) {
                                printf('<p><strong>%s:</strong>&nbsp;<span>%s</span></p>', $size, $qty);
                            }
                        }
                        break;
                    case 'instructions_questions':
                        if (!empty($value)) {
                            printf('<p><strong>Instructions/Questions:</strong>&nbsp;<span>%s</span></p>', nl2br($value));
                        }
                        break;
                    case 'location':
                        foreach ($value as $location => $location_values) {
                            if (!empty($location_values['chosen']) &&
                                    !empty($location_values['number_ink_colors'])
                            ) {
                                $chosen_string = $location_values['chosen'];
                                if (!empty($location_values['choose_ink_styles'])) {
                                    $chosen_string .= ', Ink Style: ' . $location_values['choose_ink_styles'];
                                }
                                if (!empty($location_values['choose_width'])) {
                                    $chosen_string .= ', Width: ' . $location_values['choose_width'];
                                }
                                if (!empty($location_values['choose_height'])) {
                                    $chosen_string .= ', Height: ' . $location_values['choose_height'];
                                }
                                if (!empty($location_values['choose_notes'])) {
                                    $chosen_string .= ', Notes: ' . $location_values['choose_notes'];
                                }
                                $chosen_string .= ', # Ink Colors: ' . $location_values['number_ink_colors'];
                                printf('<p><strong>%s:</strong>&nbsp;<span>%s</span></p>', $location, $chosen_string);
                            }
                        }
                        break;
                }
            }
            if ($echo && (is_admin() || is_account_page())) {
                $directory = !empty($data['cart_item_key']) ? $data['cart_item_key'] : (!empty($data['directory']) ? $data['directory'] : '');
                $upload_dir = sprintf($this->upload_directory, $directory);
                if (!empty($directory) && is_dir($upload_dir)) {
                    echo '<p><strong>View/Download Images:</strong></p>';
                    $upload_dir_uri = sprintf($this->upload_directory_uri, $directory);
                    foreach ($this->getAllFiles($upload_dir) as $file) {
                        printf('<p><a %1$s href="%2$s%3$s">%3$s</a></p>', ((is_account_page()) ? 'data-fancybox="' . esc_attr($directory) . '_images"' : 'target="_blank"'), $upload_dir_uri, $file);
                    };
                }
            }
            if (!$echo) {
                $displayDesignData = ob_get_clean();
                return $displayDesignData;
            }
        }
    }

    public function orderItemNeedsProcessing($needs_processing, $product, $order_id) {
        if (function_exists('is_fancy_product') && is_fancy_product($product->id)) {
            $needs_processing = false;
        }
        return $needs_processing;
    }

    public function printavoOrderCreate($result, $order_id) {
        $order_note = '';
        $order = wc_get_order($order_id);
        $printavo_order_api_data = $this->printavoOrderData($order);
//        $this->printRFormatted($printavo_order_api_data);
//        exit;
        if (!empty($printavo_order_api_data)) {
            $url = trailingslashit($this->printavo_api_url) . 'orders' . $this->printavoApiUriQueryString();
            $request = wp_remote_post($url, array(
                'body' => json_encode($printavo_order_api_data),
                'headers' => array(
                    'content-type' => 'application/json',
                    'accept-charset' => 'utf-8',
                    'connection' => 'keep-alive'
                )
            ));
            $body = json_decode($request['body'], true);
            $update_meta = (
                    !is_wp_error($request) &&
                    in_array($request['response']['code'], array(200, 201)) &&
                    !empty($body) &&
                    is_array($body) &&
                    !empty($body['id'])
                    );
            if ($update_meta) {
                $order->add_meta_data(self::PRINTAVO_ORDER_ID_META_KEY, $body['id'], true);
                $order->save_meta_data();
                $order->add_order_note('Printavo Order #' . sprintf('<a target="_blank" rel="noopener noreferrer" href="%s">%d</a>', trailingslashit($this->printavo_invoice_url) . $body['id'], $body['id']) . '.');
                $order->update_status('completed');
            } elseif (is_wp_error($request) && !empty($request->get_error_messages())) {
                $order->add_order_note('Printavo Order: ' . join('<br />', $request->get_error_messages()));
            } elseif (!empty($body['error'])) {
                $order->add_order_note('Printavo Order: ' . $body['error'] . ((!empty($body['details'])) ? ': ' . (is_array($body['details']) ? implode('<br />', $body['details']) : $body['details']) : ''));
            } elseif (!empty($body['error_message'])) {
                $order->add_order_note('Printavo Order: ' . $body['error_message']);
            } elseif (empty($body['id']) && empty($body['error_message'])) {
                $order->add_order_note('Printavo Order Number Empty');
            }
        }
//        $this->printRFormatted($body);
//        $this->printRFormatted(json_encode($printavo_order_api_data));
//        $log_file = ABSPATH . '/log_fields.log';
//        $f = fopen($log_file, 'a');
//        fwrite($f, "POST BODY\n\r");
//        fwrite($f, var_export($body, true));
//        fwrite($f, "RESULT\n\r");
//        fwrite($f, var_export($result, true));
//        fwrite($f, "\n\r\n\r printavo_order_api_data\n\r");
//        fwrite($f, var_export($printavo_order_api_data, true));
//        fwrite($f, "\n\r\n\r KEY\n\r");
//        fwrite($f, var_export($order->get_meta(self::PRINTAVO_ORDER_ID_META_KEY), true));
//        fclose($f);
        return $result;
    }

    public function printavoOrderUpdate($post_id, $post) {
        if ('shop_order' === $post->post_type &&
                ((class_exists('Jetpack') && !\Automattic\Jetpack\Constants::is_defined('WOOCOMMERCE_CHECKOUT')) ||
                !defined('WOOCOMMERCE_CHECKOUT'))
        ) {
//            $this->printavoOrderCreate(array(), $post_id);
//            $order = wc_get_order($post_id);
//            $printavo_order_id = $order->get_meta(self::PRINTAVO_ORDER_ID_META_KEY);
//            if (!empty($printavo_order_id)) {
//                $printavo_order_api_data = $this->printavoOrderData($order);
//                $url = trailingslashit($this->printavo_api_url) . 'orders/' . $printavo_order_id . $this->printavoApiUriQueryString();
//                $args = array(
//                    'method' => 'PUT',
//                    'body' => json_encode($printavo_order_api_data),
//                    'headers' => array(
//                        'content-type' => 'application/json',
//                        'accept-charset' => 'utf-8',
//                        'connection' => 'keep-alive'
//                    )
//                );
//                $put = wp_remote_request($url, $args);
//                if (!is_wp_error($put) && 200 == $put['response']['code'] && !empty($put['body'])) {
//                    $body = json_decode($put['body'], true);
//                    if (!empty($body) && is_array($body)) {
//                        $order->add_order_note('Printavo Order #' . $printavo_order_id . ' updated');
//                    } else {
//                        if (!empty($put->get_error_messages())) {
//                            $order->add_order_note('Printavo Order Error(s):' . join('<br />', $put->get_error_messages()));
//                        } else {
//                            $order->add_order_note('Printavo Order Update Error');
//                        }
//                    }
//                }
//            }
        }
        return $post_id;
    }

    private function initPrintavoSettings() {
        foreach ($this->printavo_advanced_custom_fields as $field) {
            $this->$field = get_field($field, 'options');
        }
        $this->printavo_uri_params['email'] = $this->printavo_api_email;
        $this->printavo_uri_params['token'] = $this->printavo_api_token;
    }

    private function initFileStackSettings() {
        foreach ($this->filestack_settings as $field) {
            $this->$field = get_field($field, 'options');
        }
    }

    private function filestackClientInit() {
//        $this->filestack_security = new FilestackSecurity($filestackApiKeys['security_key']);
//        $this->filestack_client = new FilestackClient($filestackApiKeys['api_key'], $this->filestack_security);
        $this->filestack_client = new FilestackClient($this->filestack_api_token);
    }

    private function filestackUploadApi($file = '', $file_renamed = '') {
        $file_data = array();
        if (!empty($file) &&
                is_file($file) &&
//                $this->filestack_security instanceof FilestackSecurity &&
                $this->filestack_client instanceof FilestackClient
        ) {
            try {
//                $uploaded_filelink = $this->filestack_client->upload($file);
//                $file_handle = $uploaded_filelink->handle;
//                $filelink = new Filelink($file_handle, $filestackApiKeys['api_key'], $this->filestack_security);
                $options = array();
                if (!empty($file_renamed)) {
                    $options['filename'] = $file_renamed;
                }
                $filelink = $this->filestack_client->upload($file, $options);
                $file_data['meta_data'] = $this->filestack_client->getMetaData($filelink->handle);
                $file_data['cdn_url'] = $this->filestack_client->getCdnUrl($filelink->handle);
//            $file_data['content'] = $this->filestack_client->getContent($filelink->handle);
            } catch (FilestackException $ex) {
                $file_data['error'] = $ex->getCode() . ': ' . $ex->getMessage();
            }
        }
        return $file_data;
    }

    private function updateUserMeta($user, $meta_key, $meta_value) {
        update_user_meta($user, $meta_key, wc_clean($meta_value));
    }

    private function advancedCustomFieldsValidateInput($input_array = array(), $sub_field_name = '', $validate_text = true) {
        if (!empty($sub_field_name) &&
                !empty($input_array) &&
                is_array($input_array) &&
                !empty($input_array['key']) &&
                !empty($input_array['sub_fields']) &&
                is_array($input_array['sub_fields'])
        ) {
            $input_key = '';
            foreach ($input_array['sub_fields'] as $sub_field) {
                if ($sub_field_name == $sub_field['name']) {
                    $input_key = $sub_field['key'];
                    break;
                }
            }
            if (!empty($input_key)) {
                $input_chosen = (($validate_text) ?
                        array_filter(
                                array_count_values(
                                        array_map(function($v) {
                                            return strtolower(trim(preg_replace(self::ADVANCED_CUSTOM_FIELDS_TEXT_REG_EX, ' ', sanitize_text_field($v))));
                                        }, array_column($_POST['acf'][$input_array['key']], $input_key)
                                        )
                                ), function($count) {
                            return $count > 1;
                        }) :
                        array_filter(
                                array_count_values(
                                        array_column($_POST['acf'][$input_array['key']], $input_key)
                                ), function($count) {
                            return $count > 1;
                        }));
                if (!empty($input_chosen)) {
                    foreach ($_POST['acf'][$input_array['key']] as $row => $input) {
                        $valid = true;
                        if (($validate_text && key_exists(strtolower(trim(preg_replace(self::ADVANCED_CUSTOM_FIELDS_TEXT_REG_EX, ' ', sanitize_text_field($input[$input_key])))), $input_chosen)) ||
                                key_exists($input[$input_key], $input_chosen)
                        ) {
                            $valid = false;
                        }
                        if (!$valid) {
                            acf_add_validation_error('acf[' . $input_array['key'] . '][' . $row . '][' . $input_key . ']', 'Please check this input to proceed');
                        }
                    }
                }
            }
        }
    }

    private function deleteImages($directory, $recursive = true) {
        if (!empty($directory) &&
                self::ZEN_FPD_IMPORT_FOLDER != basename($directory) &&
                file_exists($directory)
        ) {
            $wp_file_system = new WP_Filesystem_Direct('');
            $wp_file_system->delete($directory, $recursive);
        }
    }

    private function sanitizeProductPostData() {
        $_POST = stripslashes_deep($_POST);
        foreach ($_POST as $post_key => $post_value) {
            switch ($post_key) {
                case 'update_cart':
                case 'update_saved_design':
                case 'instructions_questions':
                    $_POST[$post_key] = sanitize_textarea_field($post_value);
                    break;
                case 'color':
                case 'design_name':
                    $_POST[$post_key] = sanitize_text_field($post_value);
                    break;
                case 'size':
                    foreach ($post_value as $size => $qty) {
                        if (!empty($qty)) {
                            $post_value[$size] = absint($qty);
                        }
                    }
                    $_POST[$post_key] = $post_value;
                    break;
                case 'location':
                    foreach ($post_value as $location_values_key => $location_values) {
                        foreach ($location_values as $location_value_key => $location_value) {
                            if (!empty($location_value)) {
                                switch ($location_value_key) {
                                    case 'chosen':
                                        $post_value[$location_values_key][$location_value_key] = sanitize_text_field($location_value);
                                        break;
                                    case 'number_ink_colors':
                                        $post_value[$location_values_key][$location_value_key] = absint($location_value);
                                        break;
                                    case 'choose_ink_styles':
                                        $post_value[$location_values_key][$location_value_key] = $location_value;
                                        break;
                                    case 'choose_width':
                                        $post_value[$location_values_key][$location_value_key] = floatval(sanitize_text_field($location_value));
                                        break;
                                    case 'choose_height':
                                        $post_value[$location_values_key][$location_value_key] = floatval(sanitize_text_field($location_value));
                                    case 'choose_notes':
                                        $post_value[$location_values_key][$location_value_key] = wp_kses_post($location_value);
                                        break;
                                }
                            }
                        }
                    }
                    $_POST[$post_key] = $post_value;
                    break;
            }
        }
    }

    private function orderedItemMetaData($item_id) {
        $fpd_data = wc_get_order_item_meta($item_id, self::ZEN_FPD_ORDER_ITEM_META);
        $this->displayDesignData($fpd_data);
    }

    private function getAllFiles($directory, $get_full_path = false) {
        $all_files = array();
        if (is_dir($directory)) {
            $fileSPLObjects = new RecursiveIteratorIterator(
                    new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST
            );
            foreach ($fileSPLObjects as $fullFileName => $fileSPLObject) {
                if (is_file($fullFileName)) {
                    $all_files[] = (($get_full_path) ? $fullFileName : $fileSPLObject->getFilename());
                }
            }
        }
        return $all_files;
    }

    private function saveImages($directory, &$fpd_data) {
        $result = false;
        $base64_images = (!empty($fpd_data['shirt_artwork']) && is_array($fpd_data['shirt_artwork'])) ? $fpd_data['shirt_artwork'] : array();
        if (!empty($base64_images) && !empty($directory)) {
            $upload_dir = sprintf($this->upload_directory, $directory);
            if (!file_exists($upload_dir)) {
                wp_mkdir_p($upload_dir);
            }
            foreach ($base64_images as $base64_image_name => $base64_image) {
                $result = $this->isImage($base64_image);
                if (!$result) {
                    break;
                }
                $base64_str = substr($base64_image, strpos($base64_image, ",") + 1);
                $result = file_put_contents($upload_dir . $base64_image_name . '.png', base64_decode($base64_str));
                if (!$result) {
                    break;
                }
            }
            if ($result) {
                $json_product_data = json_decode($fpd_data['product_data'], true);
                if (!empty($json_product_data) && is_array($json_product_data)) {
                    if (!empty($directory)) {
                        $this->uploadFiles($directory, $json_product_data);
                    }
                    $fpd_data['product_data'] = json_encode($json_product_data);
                }
            } else {
                $this->deleteImages($upload_dir);
            }
        }
        return $result;
    }

    private function uploadFiles($directory, &$fpd_product_data) {
        $files_uploaded = true;
        if (!empty($directory)) {
            $upload_dir = sprintf($this->upload_directory, $directory);
            $upload_dir_uri = sprintf($this->upload_directory_uri, $directory);
            if (!file_exists($upload_dir)) {
                $files_uploaded = wp_mkdir_p($upload_dir);
            }
            if ($files_uploaded) {
                foreach ($fpd_product_data as $product_data_key => &$product_data) {
                    foreach ($product_data['elements'] as $element_key => $element) {
                        foreach ($_FILES['location']['name'] as $location_name => $location) {
                            if (UPLOAD_ERR_OK === $_FILES['location']['error'][$location_name]['file'] &&
                                    strtolower($element['title']) == strtolower($location_name)) {
                                $tmp_name = $_FILES['location']['tmp_name'][$location_name]['file'];
                                $uploaded_file_info = pathinfo($_FILES['location']['name'][$location_name]['file']);
                                $name = str_replace(' ', '-', $location_name) . '.' . $uploaded_file_info['extension'];
                                if (!move_uploaded_file($tmp_name, $upload_dir . $name)) {
                                    $files_uploaded = false;
                                    break;
                                }
                                if (!$this->findReplaceInArray($product_data, $element['source'], $upload_dir_uri . $name)) {
                                    $files_uploaded = false;
                                    break;
                                }
                            }
                        }
                    }
                }
                if (!$files_uploaded) {
                    $this->deleteImages($upload_dir);
                }
            }
        }
        return $files_uploaded;
    }

    private function findReplaceInArray(&$array, $find, $replace) {
        return array_walk_recursive($array, function(&$item, $key, $find_replace) {
            if ('source' == $key && $item == $find_replace[0]) {
                $item = $find_replace[1];
            }
        }, array($find, $replace));
    }

    private function isImage($url) {
        $img_formats = array("image/png", "image/jpg", "image/jpeg", "image/svg");
        if ($this->isBase64($url)) {
            $key = false;
            foreach ($img_formats as $k => $img_format) {

                if (strpos($url, $img_format) !== false) {
                    $key = $k;
                }
            }
            return $key === false ? false : $img_formats[$key];
        } else {
            $img_info = getimagesize($url);
            $key = array_search(strtolower($img_info['mime']), $img_formats);
            return $key === false ? false : $img_formats[$key];
        }
    }

    private function isBase64($data_uri_str) {
        $regex = '/^data:(.+?){0,1}(?:(?:;(base64)\,){1}|\,)(.+){0,1}$/';
        return (preg_match($regex, $data_uri_str) === 1);
    }

    private function addFieldsChoices($field, $post_id = 'options') {
        if (key_exists($field['name'], $this->acf_fields) && isset($field['choices']) && is_array($field['choices'])) {
            $get_field_values = get_field($field['name'], $post_id);
            if (is_array($get_field_values)) {
                $choices = array_map('trim', array_column($get_field_values, $this->acf_fields[$field['name']]));
                $field['choices'] = array();
                if (is_array($choices)) {
                    foreach ($choices as $choice) {
                        if (!empty($choice)) {
                            $field['choices'][$choice] = $choice;
                        }
                    }
                }
            }
        }
        if (isset($field['sub_fields']) && is_array($field['sub_fields'])) {
            foreach ($field['sub_fields'] as &$sub_field) {
                if (key_exists($sub_field['name'], $this->acf_fields)) {
                    $get_field_values = get_field($sub_field['name'], $post_id);
                    if (!empty($get_field_values)) {
                        if (is_numeric($get_field_values)) {
                            $get_field_values = range(1, $get_field_values);
                        }
                        if (is_string($get_field_values)) {
                            $get_field_values = array($get_field_values);
                        }
                        if (is_array($get_field_values)) {
                            $choices = array_map('trim', array_column($get_field_values, $this->acf_fields[$sub_field['name']]));
                            if (empty($choices)) {
                                $choices = $get_field_values;
                            }
                            $sub_field['choices'] = array();
                            if (is_array($choices)) {
                                foreach ($choices as $choice) {
                                    if (!empty($choice)) {
                                        $sub_field['choices'][$choice] = $choice;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return $field;
    }

    private function initAdminAdvancedCustomFieldsSettings() {
        if (is_admin() && $this->advancedCustomFieldsIsValid()) {
            acf_add_options_page(array(
                'page_title' => 'Zen Agency - Fancy Product Designer Settings',
                'menu_title' => 'Zen Agency - Fancy Product Designer Settings',
                'menu_slug' => self::ADVANCED_CUSTOM_FIELDS_SLUG,
                'redirect' => false
            ));
        }
    }

    private function advancedCustomFieldsIsValid() {
        $is_valid = false;
        if (in_array(self::ADVANCED_CUSTOM_FIELDS, $this->active_plugins) &&
                function_exists('acf_add_options_page')
        ) {
            $is_valid = true;
        }
        return $is_valid;
    }

    private function fancyProductDesignerIsValid() {
        $is_valid = false;
        if (in_array(self::FANCY_PRODUCT_DESIGNER, $this->active_plugins) &&
                class_exists('FPD_Frontend_Product') &&
                method_exists('FPD_Frontend_Product', 'add_product_designer') &&
                class_exists('FPD_Product') &&
                method_exists('FPD_Product', 'to_JSON') &&
                class_exists('FPD_Product_Settings') &&
                function_exists('fpd_has_content') &&
                function_exists('is_fancy_product')
        ) {
            $is_valid = true;
        }
        return $is_valid;
    }

    private function printavoApiUriQueryString($query_params = array()) {
        if (!empty($query_params)) {
            $this->printavo_uri_params = array_merge($this->printavo_uri_params, $query_params);
        }
        return '?' . http_build_query($this->printavo_uri_params);
    }

    private function printavoOrderStatuses() {
        $wc_order_statuses = wc_get_order_statuses();
        $get = wp_remote_get(
                trailingslashit($this->printavo_api_url) . 'orderstatuses' . $this->printavoApiUriQueryString(array('per_page' => 100))
        );
        if (!is_wp_error($get) && 200 == $get['response']['code'] && !empty($get['body'])) {
            $body = json_decode($get['body'], true);
            if (!empty($body['data']) && is_array($body['data'])) {
                foreach ($body['data'] as $status) {
                    if (!key_exists('wc-printavo_' . $status['id'], $wc_order_statuses)) {
                        $post_id = wp_insert_post(array(
                            'post_name' => 'printavo_' . $status['id'],
                            'post_title' => $status['name'],
                            'post_type' => 'wc_order_status',
                            'post_status' => 'publish'
                        ));
                        update_post_meta($post_id, '_color', $status['color']);
                        usleep(500000);
                    } else {
                        $this->printRFormatted($status);
                    }
                }
            }
        }
    }

    private function printavoUser() {
        $user = array();
        // array('per_page' => 100) ... grab top 50 users... assuming there won't be more than 100?
        $get = wp_remote_get(
                trailingslashit($this->printavo_api_url) . 'users' . $this->printavoApiUriQueryString(array('per_page' => 100))
        );
        $body = json_decode($get['body'], true);
        $users_exists = (
                !is_wp_error($get) &&
                200 == $get['response']['code'] &&
                !empty($body) &&
                is_array($body) &&
                !empty($body['data']) &&
                is_array($body['data'])
                );
        if ($users_exists) {
            $user_key = array_search($this->printavo_api_email, array_column($body['data'], 'email'));
            if (false === $user_key) {
                $user_key = 0;
            }
            $user = $body['data'][$user_key];
        } elseif (is_wp_error($get) && !empty($get->get_error_messages())) {
            $user['error_message'] = join('<br />', $get->get_error_messages());
        } elseif (!empty($body['error'])) {
            $user['error_message'] = $body['error'] . ((!empty($body['details'])) ? ': ' . $body['details'] : '');
        } elseif (!empty($body['error_message'])) {
            $user['error_message'] = $body['error_message'];
        } elseif (empty($body['id']) && empty($body['error_message'])) {
            $user['error_message'] = 'ID Empty';
        }
        return $user;
    }

    private function printavoShowCustomer($user_id = 0) {
        $body = array();
        if (!empty($user_id) && is_numeric($user_id)) {
            $printavo_customer_id = get_user_meta($user_id, self::PRINTAVO_CUSTOMER_ID_META_KEY, true);
            if (!empty($printavo_customer_id) && is_numeric($printavo_customer_id)) {
                $url = trailingslashit($this->printavo_api_url) . 'customers/' . $printavo_customer_id . $this->printavoApiUriQueryString();
                $get = wp_remote_get($url);
                if (!is_wp_error($get) && 200 == $get['response']['code'] && !empty($get['body'])) {
                    $body = json_decode($get['body'], true);
//                            if (!empty($body) && is_array($body)) {
//                                $this->printRFormatted($body);
//                            }
                } else {
                    // ??
                }
            }
        }
        return $body;
    }

    private function printavoSearchCustomer($email = '') {
        if (!empty($email)) {
            $url = trailingslashit($this->printavo_api_url) . 'customers/search' . $this->printavoApiUriQueryString(array('query' => $email));
            $get = wp_remote_get($url);
            if (!is_wp_error($get) && 200 == $get['response']['code'] && !empty($get['body'])) {
                $body = json_decode($get['body'], true);
                if (!empty($body['data']) && is_array($body['data'])) {
                    return $body['data'][0];
                }
            } else {
                // ??
            }
        }
        return array();
    }

    private function printavoSetCustomer($order = null, $printavo_user_id = 0) {
        $body = array();
        if ($order instanceof WC_Order) {
            $user_id = $order->get_user_id();
            $default_address_args = array(
                'first_name' => '',
                'last_name' => '',
                'company' => '',
                'address_1' => '',
                'address_2' => '',
                'city' => '',
                'state' => '',
                'postcode' => '',
                'country' => '',
            );
            if (!empty($user_id) && is_numeric($user_id)) {
                $user_data = get_user_by('id', $user_id);
                $printavo_customer_id = get_user_meta($user_id, self::PRINTAVO_CUSTOMER_ID_META_KEY, true);
                $first_name = $user_data->first_name;
                $last_name = $user_data->last_name;
                $customer_email = $user_data->user_email;
                $billing_address = array_map('trim', wp_parse_args($this->getCustomerAddress('billing', $user_id), $default_address_args));
                $billing_state = $this->states[$billing_address['country']][$billing_address['state']] ?? $billing_address['state'];
                $shipping_address = array_map('trim', wp_parse_args($this->getCustomerAddress('shipping', $user_id), $default_address_args));
                $shipping_state = $this->states[$shipping_address['country']][$shipping_address['state']] ?? $shipping_address['state'];
            } else {
                $printavo_customer = $this->printavoSearchCustomer($order->get_billing_email());
                $printavo_customer_id = $printavo_customer['id'] ?? '';
                $first_name = $order->get_billing_first_name();
                $last_name = $order->get_billing_last_name();
                $customer_email = $order->get_billing_email();
                $billing_address = array_map('trim', wp_parse_args($order->get_address('billing'), $default_address_args));
                $billing_state = $this->states[$billing_address['country']][$billing_address['state']] ?? $billing_address['state'];
                $shipping_address = array_map('trim', wp_parse_args($order->get_address('shipping'), $default_address_args));
                $shipping_state = $this->states[$shipping_address['country']][$shipping_address['state']] ?? $shipping_address['state'];
            }
            $has_printavo_customer_id = (!empty($printavo_customer_id) && is_numeric($printavo_customer_id));
            $post_data = array(
                'first_name' => $first_name,
                'last_name' => $last_name,
                'customer_email' => $customer_email,
                'user_id' => $printavo_user_id,
                'phone' => $billing_address['phone'] ?? '',
                'company' => !empty($billing_address['company']) ? $billing_address['company'] : 'N/A',
                'billing_address_attributes' => array(
                    'address1' => $billing_address['address_1'] ?? '',
                    'address2' => $billing_address['address_2'] ?? '',
                    'city' => $billing_address['city'] ?? '',
                    'state' => $billing_state ?? '',
                    'zip' => $billing_address['postcode'] ?? '',
                    'country' => $billing_address['country'] ?? ''
                ),
                'shipping_address_attributes' => array(
                    'address1' => $shipping_address['address_1'] ?? '',
                    'address2' => $shipping_address['address_2'] ?? '',
                    'city' => $shipping_address['city'] ?? '',
                    'state' => $shipping_state ?? '',
                    'zip' => $shipping_address['postcode'] ?? '',
                    'country' => $shipping_address['country'] ?? ''
                )
            );
            $action = 'create';
            $url = trailingslashit($this->printavo_api_url) . 'customers';
            if ($has_printavo_customer_id) {
                $action = 'update';
                $url .= '/' . $printavo_customer_id;
            }
            $url .= $this->printavoApiUriQueryString();
            $args = array(
                'body' => json_encode($post_data),
                'headers' => array(
                    'content-type' => 'application/json',
                    'accept-charset' => 'utf-8',
                    'connection' => 'keep-alive'
                )
            );
            switch ($action) {
                case 'create':
                    $request = wp_remote_post($url, $args);
                    break;
                case 'update':
                    $args['method'] = 'PUT';
                    $request = wp_remote_request($url, $args);
                    break;
            }
            $body = json_decode($request['body'], true);
            $update_meta = (
                    !is_wp_error($request) &&
                    in_array($request['response']['code'], array(200, 201)) &&
                    !empty($body) &&
                    is_array($body) &&
                    !empty($body['id'])
                    );
            if ($update_meta) {
                $this->updateUserMeta($user_id, self::PRINTAVO_CUSTOMER_ID_META_KEY, $body['id']);
            } else {
                // if we tried to update the user, but it fails, 
                // just try to create the order in Printavo using existing user id
                $body = array();
                if ($has_printavo_customer_id) {
                    $body['id'] = $printavo_customer_id;
                } else {
                    if (is_wp_error($request) && !empty($request->get_error_messages())) {
                        $body['error_message'] = join('<br />', $request->get_error_messages());
                    } elseif (!empty($body['error'])) {
                        $body['error_message'] = $body['error'] . ((!empty($body['details'])) ? ': ' . $body['details'] : '');
                    } elseif (empty($body['id']) && empty($body['error_message'])) {
                        $body['error_message'] = 'ID empty';
                    }
                }
            }
        }
        return $body;
    }

    private function printavoOrderData($order) {
        $printavo_user = $this->printavoUser();
        if (!empty($printavo_user['error_message'])) {
            $order->add_order_note('Printavo User Error(s): ' . $printavo_user['error_message']);
            return array();
        }
        $printavo_customer = $this->printavoSetCustomer($order, $printavo_user['id']);
        if (!empty($printavo_customer['error_message'])) {
            $order->add_order_note('Printavo Customer Error(s): ' . $printavo_customer['error_message']);
            return array();
        }
        $production_notes = '';
        $order_number = $order->get_id();
        $lineitems_attributes = array();
        $this->filestackClientInit();
        $line_item = 1;
        foreach ($order->get_items() as $item) {
            $zen_fpd_data = $item->get_meta(self::ZEN_FPD_ORDER_ITEM_META);
            if (!empty($zen_fpd_data)) {
                $upload_dir = sprintf($this->upload_directory, $zen_fpd_data['cart_item_key']);
                $images_attributes = array();
//                $production_notes_files_attributes = array();
                foreach ($this->getAllFiles($upload_dir) as $file) {
                    $filestack_response = $this->filestackUploadApi($upload_dir . $file, $order_number . '_line_item_' . $line_item . '_' . $file);
                    if (!empty($filestack_response) && empty($filestack_response['error'])) {
                        $images_attributes[] = array(
                            'file_url' => $filestack_response['cdn_url'] ?? '',
                            'mime_type' => $filestack_response['meta_data']['mimetype'] ?? ''
                        );
//                        $production_notes_files_attributes[] = array(
//                            'file_url' => $filestack_response['cdn_url'] ?? '',
//                            'mime_type' => $filestack_response['meta_data']['mimetype'] ?? ''
//                        );
                    } else {
                        $order->add_order_note('Filestack Error' . ((!empty($filestack_response['error'])) ? ': ' . $filestack_response['error'] : ''));
                    }
                };
                $unit_cost = floatval($item->get_total());
                $qty = array_sum($zen_fpd_data['size']);
                $sizes = array();
                foreach ($zen_fpd_data as $key => $value) {
                    if ('size' == $key) {
                        foreach ($value as $size => $size_qty) {
                            if (is_numeric($size_qty)) {
                                $sizes['size_' . strtolower($size)] = $size_qty;
                            }
                        }
                    }
                }
                $lineitems_attributes[] = array_merge(array(
                    'style_number' => $item->get_product()->get_sku(),
                    'color' => $zen_fpd_data['color'],
                    'unit_cost' => ($unit_cost / $qty),
//                    'size_other' => $qty,
                    'taxable' => ('taxable' === $item->get_tax_status()),
                    'images_attributes' => $images_attributes
                        ), $sizes);
                $production_notes .= '<p>Line Item: ' . $line_item . '</p>' . trim($this->displayDesignData($zen_fpd_data, false)) . '<br/>';
            }
            $line_item++;
        }

        $hidden_order_itemmeta = apply_filters(
                'woocommerce_hidden_order_itemmeta', array(
            '_qty',
            '_tax_class',
            '_product_id',
            '_variation_id',
            '_line_subtotal',
            '_line_subtotal_tax',
            '_line_total',
            '_line_tax',
            'method_id',
            'cost',
            '_reduced_stock',
            '_restock_refunded_items',
                )
        );
        foreach ($order->get_items('shipping') as $item_id => $item) {
            $production_notes .= '<p>' . esc_html($item->get_name() ? $item->get_name() : __('Shipping', 'woocommerce')) . '</p>';
            foreach ($item->get_formatted_meta_data('') as $meta_id => $meta) {
                if (in_array($meta->key, $hidden_order_itemmeta, true)) {
                    continue;
                }
                $production_notes .= '<p>' . wp_strip_all_tags($meta->display_key . ': ' . $meta->display_value, true) . '</p>';
            }
        }

        $date_created = new DateTimeImmutable($order->get_date_created());
        $due_date = $date_created->modify('+' . $this->printavo_default_customer_order_due_date_interval . ' days')->format('m/d/Y');

        $billing_company = $order->get_billing_company();
        $billing_name = trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name());
        $billing_address1 = $order->get_billing_address_1();
        $billing_address2 = $order->get_billing_address_2();
        $billing_city = $order->get_billing_city();
        $billing_state = $this->states[$order->get_billing_country()][$order->get_billing_state()] ?? $order->get_billing_state();
        $billing_zip = $order->get_billing_postcode();
        $billing_country = $order->get_billing_country();

        $shipping_company = $order->get_shipping_company();
        $shipping_name = trim($order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name());
        $shipping_address1 = $order->get_shipping_address_1();
        $shipping_address2 = $order->get_shipping_address_2();
        $shipping_city = $order->get_shipping_city();
        $shipping_state = $this->states[$order->get_shipping_country()][$order->get_shipping_state()] ?? $order->get_shipping_state();
        $shipping_zip = $order->get_shipping_postcode();
        $shipping_country = $order->get_shipping_country();

        return array(
            'user_id' => absint($printavo_user['id']),
            'customer_id' => absint($printavo_customer['id']),
            'orderstatus_id' => str_replace('printavo_', '', $this->printavo_default_invoice_status_id),
            'formatted_due_date' => $due_date,
            'formatted_customer_due_date' => $due_date,
            'production_notes' => $production_notes,
            'order_addresses_attributes' => array(
                array(
                    'name' => 'Customer Billing',
                    'company_name' => $billing_company,
                    'customer_name' => $billing_name,
                    'address1' => $billing_address1,
                    'address2' => $billing_address2,
                    'city' => $billing_city,
                    'state' => $billing_state,
                    'zip' => $billing_zip,
                    'country' => $billing_country
                ),
                array(
                    'name' => 'Customer Shipping',
                    'company_name' => !empty($shipping_company) ? $shipping_company : $billing_company,
                    'customer_name' => !empty($shipping_name) ? $shipping_name : $billing_name,
                    'address1' => !empty($shipping_address1) ? $shipping_address1 : $billing_address1,
                    'address2' => !empty($shipping_address2) ? $shipping_address2 : $billing_address2,
                    'city' => !empty($shipping_city) ? $shipping_city : $billing_city,
                    'state' => !empty($shipping_state) ? $shipping_state : $billing_state,
                    'zip' => !empty($shipping_zip) ? $shipping_zip : $billing_zip,
                    'country' => !empty($shipping_country) ? $shipping_country : $billing_country
                )
            ),
            'lineitems_attributes' => $lineitems_attributes,
//            'production_notes_files_attributes' => $production_notes_files_attributes,
            'order_fees_attributes' => array(
                array(
                    'description' => 'Shipping Fee',
                    'amount' => $order->get_shipping_total()
                )
            )
        );
    }

    private function getCustomerAddress($address_type, $customer_id) {
        $getter = "get_{$address_type}";
        $address = array();
        if (0 === $customer_id) {
            $customer_id = get_current_user_id();
        }
        $customer = new WC_Customer($customer_id);
        if (is_callable(array($customer, $getter))) {
            $address = $customer->$getter();
        }
        return $address;
    }

}

function ZenFancyProductDesigner() {
    return ZenFancyProductDesigner::instance();
}

ZenFancyProductDesigner();