<?php

if ( !defined( 'ABSPATH' ) ) {

    exit;
}

if ( !class_exists( 'Pricely_Product_Filter_Types' ) ) {

    require_once (dirname( __FILE__ ) . '/product-filter-types-product.php');

    class Pricely_Product_Filter_Types {

        private static $instance;
        private $filter_types;

        public static function get_instance(): self {

            if ( !self::$instance ) {

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

            return self::$instance;
        }

        public function validate_product( $data, $product_args ) {

            if ( !isset( $data[ 'wc' ][ 'product' ] ) ) {

                return false;
            }

            if ( !count( $data[ 'wc' ][ 'product' ] ) ) {

                return false;
            }

            if ( !count( $product_args ) ) {

                return true;
            }

            return $this->validate_filters( $data, $product_args );
        }

        private function validate_filters( $data, $product_args ) {

            $is_valid = false;

            foreach ( $this->get_filters( $product_args, true ) as $filter_args ) {

                $is_vld = $this->validate_filter( $filter_args, $data );

                if ( true === $is_vld ) {
                    $is_valid = true;
                }

                if ( true != $is_valid ) {

                    return $is_valid;
                }
            }

            if ( true === $is_valid ) {

                return $is_valid;
            }

            foreach ( $this->get_filters( $product_args, false ) as $filter_args ) {

                $is_vld_op = $this->validate_filter( $filter_args, $data );

                if ( true === $is_vld_op ) {

                    $is_valid = true;
                }
            }

            return $is_valid;
        }

        private function validate_filter( $filter_args, $data ) {
            
            if ( class_exists( 'Pricely_Pro_Product_Filter_Types' ) ) {

                return Pricely_Pro_Product_Filter_Types::get_instance()->validate_filter( $filter_args, $data );
            }

            foreach ( $this->load_filter_types() as $filter_type ) {

                if ( $filter_type->can_validate( $filter_args[ 'filter_type' ] ) ) {

                    return $filter_type->validate( $filter_args, $data );
                }
            }

            return false;
        }

        private function get_filters( $product_filters, $is_required ) {

            $filters = array();

            foreach ( $product_filters as $product_filter ) {

                $filter_type = $product_filter[ 'filter_type' ];
                $filter_arg = $product_filter[ 'filter_type_' . $filter_type ];

                if ( true == $is_required && 'yes' != $filter_arg[ 'is_req' ] ) {

                    continue;
                }

                if ( true != $is_required && 'yes' == $filter_arg[ 'is_req' ] ) {

                    continue;
                }


                $filters[] = $this->prepare_filter( $filter_arg, $filter_type );
            }

            return $filters;
        }

        private function prepare_filter( $filter_args, $filter_type ) {

            $filter = array(
                'filter_type' => $filter_type
            );

            foreach ( $filter_args as $key => $value ) {

                $filter[ $key ] = $value;
            }

            return $filter;
        }

        private function load_filter_types() {

            if ( !is_null( $this->filter_types ) ) {

                return $this->filter_types;
            }

            $this->filter_types = array();

            foreach ( $this->register_filter_types() as $key => $filter_type ) {

                if ( !class_exists( $filter_type ) ) {

                    continue;
                }
                
                if ( !method_exists( $filter_type, 'can_validate' ) ) {
                  
                    continue;
                }
                
                if ( !method_exists( $filter_type, 'validate' ) ) {
                  
                    continue;
                }

                if ( method_exists( $filter_type, 'get_instance' ) ) {

                    $this->filter_types[ $key ] = $filter_type::get_instance();
                } else {

                    $this->filter_types[ $key ] = new $filter_type();
                }
            }

            return $this->filter_types;
        }

        private function register_filter_types() {

            $filter_types = array(
                'product' => 'Pricely_Product_Filter_Type_Product',
            );

            return apply_filters( 'pricely_register-product-filter-types', $filter_types );
        }

    }

}
