<?php

if ( !defined( 'ABSPATH' ) ) {
    exit;
}


if ( !class_exists( 'Reon_Meta_Box_WC' ) ) {

    class Reon_Meta_Box_WC {

        private static $instance;
        private static $post_metaboxes;
        private static $metaboxes;
        private static $product_type_options = array();

        public static function get_instance(): self {

            if ( !self::$instance ) {

                self::$instance = new self();
            }

            return self::$instance;
        }

        public static function init() {

            $metaboxes = array();
            $product_type_options = array();

            add_filter( 'product_type_options', array( new self(), 'product_type_options' ) );
            add_action( 'woocommerce_process_product_meta', array( new self(), 'save_product_type_options' ) );
        }

        public static function product_type_options( $product_type_options ) {
            foreach ( self::get_product_type_options() as $product_t_opt ) {
                $product_type_option = apply_filters( 'reon_get-product-type-option', $product_t_opt );

                $product_type_options[ $product_type_option[ 'id' ] ] = array(
                    'id' => $product_type_option[ 'meta_id' ],
                    'wrapper_class' => (is_array( $product_type_option[ 'wrapper_class' ] )) ? implode( ' ', $product_type_option[ 'wrapper_class' ] ) : $product_type_option[ 'wrapper_class' ],
                    'label' => $product_type_option[ 'label' ],
                    'description' => $product_type_option[ 'desc' ],
                    'default' => $product_type_option[ 'default' ]
                );
            }
            return $product_type_options;
        }

        public static function save_product_type_options( $product_id ) {

            $is_autosave = wp_is_post_autosave( $product_id );
            $is_revision = wp_is_post_revision( $product_id );

            $is_valid_nonce = (isset( $_POST[ 'woocommerce_meta_nonce' ] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST[ 'woocommerce_meta_nonce' ] ) ), 'woocommerce_save_data' ) );

            if ( $is_autosave || $is_revision || !$is_valid_nonce ) {

                return;
            }

            if ( !current_user_can( 'edit_post', $product_id ) ) {

                return;
            }

            foreach ( self::get_product_type_options() as $product_t_opt ) {

                $product_type_option = apply_filters( 'reon_get-product-type-option', $product_t_opt );

                $meta_value = 'no';

                if ( isset( $_POST[ $product_type_option[ 'meta_id' ] ] ) ) {

                    $meta_value = 'yes';
                }

                $meta_value = apply_filters( 'reon_save-product-type-option-meta', $meta_value, $product_id, $product_type_option[ 'meta_id' ] );
                update_post_meta( $product_id, $product_type_option[ 'meta_id' ], $meta_value );
            }
        }

        public static function product_tab( $metabox_id, $tabs ) {
            $metabox = self::get_metabox( $metabox_id );

            $tabs[ $metabox_id ] = array(
                'label' => $metabox[ 'title' ],
                'target' => 'rn_' . $metabox[ 'id' ],
                'class' => $metabox[ 'class' ],
                'priority' => $metabox[ 'priority' ]
            );

            return $tabs;
        }

        public static function product_tab_contents( $metabox_id, $product_id ) {
            $metabox = self::get_metabox( $metabox_id );
            $metabox[ 'fields' ] = ReonCore::process_default_post_metabox_wc_fields( apply_filters( 'reon_get-metabox-wc-' . $metabox[ 'id' ] . '-fields', $metabox[ 'fields' ], $metabox[ 'id' ], $product_id ) );
            $metabox[ 'nonce_path' ] = basename( __FILE__ );

            do_action( 'reon_render-metabox-wc', $metabox, $product_id );
        }

        public static function save_product_metabox( $metabox_id, $product_id ) {

            $is_autosave = wp_is_post_autosave( $product_id );
            $is_revision = wp_is_post_revision( $product_id );

            $is_valid_nonce = ( isset( $_POST[ 'reon_product_meta' . $metabox_id ] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST[ 'reon_product_meta' . $metabox_id ] ) ), basename( __FILE__ ) ) ) ? true : false;

            if ( $is_autosave || $is_revision || !$is_valid_nonce ) {

                return;
            }

            if ( !current_user_can( 'edit_post', $product_id ) ) {

                return;
            }

            $metabox = self::get_metabox( $metabox_id );
            $metabox[ 'fields' ] = ReonCore::process_default_post_metabox_wc_fields( apply_filters( 'reon_get-metabox-wc-' . $metabox[ 'id' ] . '-fields', $metabox[ 'fields' ], $metabox[ 'id' ], $product_id ) );

            $product_metas = array();


            $valuas_id = 'reon_metabox_' . $metabox_id . '_value';

            if ( isset( $_POST[ $valuas_id ] ) ) {

                //Sanitized below using the "sanitize_meta_option" method after json_decode() call
                $meta_vals_str = wp_kses_post( wp_unslash( $_POST[ $valuas_id ] ) );

                $meta_vals = json_decode( $meta_vals_str, true );

                if ( is_array( $meta_vals ) && isset( $meta_vals[ $metabox_id ] ) ) {
                    //Sanitization is done here
                    $sanitized_meta_vals = self::sanitize_meta_option( $metabox_id, $product_id, $meta_vals[ $metabox_id ] );

                    $product_metas = apply_filters( 'reon_save_all_' . $metabox_id . '_product_metas', $sanitized_meta_vals, $product_id );
                }
            }


            if ( $metabox[ 'save_metabox' ] == true ) {

                $field_ids = Reon_Utils::get_controls_field_ids( $metabox[ 'fields' ] );

                foreach ( $field_ids as $field_id ) {
                    if ( isset( $product_metas[ $field_id ] ) ) {
                        update_post_meta( $product_id, $field_id, $product_metas[ $field_id ] );
                    } else {
                        delete_post_meta( $product_id, $field_id );
                    }
                }
            }
        }

        public static function get_metabox( $id = '' ) {
            if ( $id == '' ) {
                return array();
            }
            foreach ( self::get_metaboxes() as $metabox ) {
                if ( $metabox[ 'id' ] == $id ) {
                    $mt = apply_filters( 'reon_get-metabox-wc', $metabox );
                    return $mt;
                }
            }
            return array();
        }

        public static function get_metaboxes() {
            return self::$post_metaboxes;
        }

        public static function get_product_type_options() {
            return self::$product_type_options;
        }

        public static function set_metabox( $args = array() ) {

            $metabox = self::default_metabox();
            foreach ( $args as $key => $value ) {
                $metabox[ $key ] = $value;
            }
            self::$post_metaboxes[] = apply_filters( 'reon_set-metabox-wc', $metabox );
            self::$metaboxes[] = new Reon_Meta_Box_WC_Renderer( $args[ 'id' ] );
        }

        public static function set_product_type_option( $args = array() ) {
            $product_type_options = self::default_product_type_option();
            foreach ( $args as $key => $value ) {
                $product_type_options[ $key ] = $value;
            }
            self::$product_type_options[] = apply_filters( 'reon_set-product-type-option', $product_type_options );
        }

        private static function default_metabox() {
            $args = array(
                'id' => 'reon',
                'title' => '',
                'priority' => 99,
                'class' => array(),
                'sanitize_mode' => 'default', // default, recursive, filter
                'save_metabox' => true,
                'clean_meta' => true,
                'fields' => array()
            );
            return $args;
        }

        private static function default_product_type_option() {

            $args = array(
                'id' => 'reon-product-type-option',
                'label' => '',
                'wrapper_class' => array(),
                'desc' => '',
                'default' => 'no'
            );
            return $args;
        }

        private static function sanitize_meta_option( $metabox_id, $post_id, $options = array() ) {

            $sanitize_mode = self::get_sanitize_mode( $metabox_id );

            if ( 'recursive' == $sanitize_mode ) {

                return self::get_recursive_sanitised_options( $metabox_id, $options );
            }

            $sanitise_filter = $metabox_id . '-options';

            if ( has_filter( 'reon_sanitize-' . $sanitise_filter ) && 'filter' == $sanitize_mode ) {

                return apply_filters( 'reon_sanitize-' . $sanitise_filter, $options );
            }

            $field_types = self::get_field_types( $metabox_id, $post_id );

            $opt = array();
            foreach ( $field_types as $field_type ) {
                if ( isset( $options[ $field_type[ 'id' ] ] ) ) {
                    $sanitize_type = $field_type[ 'type' ];
                    if ( isset( $field_type[ 'sanitize_type' ] ) ) {
                        $sanitize_type = $field_type[ 'sanitize_type' ];
                    }

                    $opt[ $field_type[ 'id' ] ] = apply_filters( 'reon_sanitize-' . $sanitize_type, $options[ $field_type[ 'id' ] ], $options[ $field_type[ 'id' ] ], $field_type[ 'id' ], $field_type[ 'children' ] );
                }
            }

            return $opt;
        }

        private static function get_recursive_sanitised_options( $in_key, $options ) {

            $opt = array();

            foreach ( $options as $option_key => $option ) {

                $filter_key = $in_key . '-' . $option_key;

                if ( is_numeric( $option_key ) ) {

                    $filter_key = $in_key;
                }

                if ( has_filter( 'reon_sanitize-' . $filter_key ) ) {

                    $opt[ $option_key ] = apply_filters( 'reon_sanitize-' . $filter_key, $option );

                    continue;
                }

                if ( is_array( $option ) ) {

                    $opt[ $option_key ] = self::get_recursive_sanitised_options( $filter_key, $option );

                    continue;
                }

                if ( $option == '<=' || $option == '<' || $option == '>=' || $option == '>=' || $option == '==' || $option == '!=' ) {

                    $opt[ $option_key ] = $option;

                    continue;
                }

                $opt[ $option_key ] = sanitize_text_field( $option );
            }

            return $opt;
        }

        private static function get_field_types( $metabox_id, $post_id ) {

            $field_args = array(
                'screen' => 'metabox-wc',
                'metabox_id' => $metabox_id,
                'post_id' => $post_id
            );

            $field_types = array();

            $metabox = self::get_metabox( $metabox_id );

            $metabox[ 'fields' ] = apply_filters( 'reon_get-metabox-wc-' . $metabox[ 'id' ] . '-fields', ReonCore::process_default_post_metabox_fields( $metabox[ 'fields' ] ), $metabox[ 'id' ], $post_id );


            foreach ( $metabox[ 'fields' ] as $field ) {

                if ( isset( $field[ 'merge_fields' ] ) && $field[ 'merge_fields' ] == false && isset( $field[ 'fields' ] ) ) {
                    foreach ( Reon_Utils::get_controls_field_types( $field[ 'fields' ], $field_args ) as $field_type ) {
                        $field_types[] = array(
                            'id' => $field_type[ 'id' ],
                            'type' => $field_type[ 'type' ],
                            'sanitize_type' => $field_type[ 'sanitize_type' ],
                            'screen' => $field_type[ 'screen' ],
                            'metabox_id' => $field_type[ 'metabox_id' ],
                            'post_id' => $field_type[ 'post_id' ],
                            'children' => $field_type[ 'children' ]
                        );
                    }
                } else {
                    $field_types[] = array(
                        'id' => $field[ 'id' ],
                        'type' => $field[ 'type' ],
                        'sanitize_type' => $field[ 'sanitize_type' ],
                        'screen' => 'metabox',
                        'metabox_id' => $metabox_id,
                        'post_id' => $post_id,
                        'children' => apply_filters( 'reon_get-' . $field[ 'type' ] . '-children-types', array(), $field, $field_args )
                    );
                }
            }
            return $field_types;
        }

        private static function get_sanitize_mode( $metabox_id ) {

            $metabox = self::get_metabox( $metabox_id );

            if ( isset( $metabox[ 'sanitize_mode' ] ) ) {

                return $metabox[ 'sanitize_mode' ];
            }

            return 'default';
        }

    }

}


if ( !class_exists( 'Reon_Meta_Box_WC_Renderer' ) ) {

    class Reon_Meta_Box_WC_Renderer {

        public $metaboxe_id;

        public function __construct( $id = '' ) {
            $this->metaboxe_id = $id;
            add_filter( 'woocommerce_product_data_tabs', array( $this, 'metabox_tab' ) );

            add_action( 'woocommerce_product_data_panels', array( $this, 'metabox_tab_content' ), 99 );
            add_action( 'woocommerce_process_product_meta', array( $this, 'save_product_metas' ) );
        }

        public function metabox_tab( $tabs ) {
            return Reon_Meta_Box_WC::product_tab( $this->metaboxe_id, $tabs );
        }

        public function metabox_tab_content() {
            global $post;
            $product_id = $post->ID;
            Reon_Meta_Box_WC::product_tab_contents( $this->metaboxe_id, $post->ID );
        }

        public function save_product_metas( $product_id ) {
            Reon_Meta_Box_WC::save_product_metabox( $this->metaboxe_id, $product_id );
        }

    }

}
