<?php

if ( !defined( 'ABSPATH' ) ) {

    exit;
}


if ( !class_exists( 'Pricely_Validation_Util' ) ) {

    class Pricely_Validation_Util {

        private static $instance;

        public static function get_instance(): self {

            if ( !self::$instance ) {

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

            return self::$instance;
        }

        public function validate_date( $validate_type, $value, $rule_value, $value_format, $rule_value_format ) {

            if ( is_string( $value ) ) {

                $value = DateTime::createFromFormat( $value_format, $value );
            }

            if ( is_string( $rule_value ) ) {

                $rule_value = DateTime::createFromFormat( $rule_value_format, $rule_value );
            }


            $c_date = $value->format( 'U' );
            $rule_c_date = $rule_value->format( 'U' );

            return $this->validate_value( $validate_type, $c_date, $rule_c_date );
        }

        public function validate_value( $validate_type, $value, $rule_value = '', $rule_yes_no = 'no' ) {

            if ( $validate_type == 'empty' ) {

                $is_empty = false;

                if ( $value == '' ) {

                    $is_empty = true;
                }

                return $this->validate_yes_no( $is_empty, $rule_yes_no );
            }

            if ( $validate_type == 'contains' ) {

                return $this->contains( $rule_value, $value );
            }

            if ( $validate_type == 'not_contains' ) {

                return !($this->contains( $rule_value, $value ));
            }

            if ( $validate_type == 'begins' ) {

                return $this->starts_with( $rule_value, $value );
            }

            if ( $validate_type == 'ends' ) {

                return $this->ends_with( $rule_value, $value );
            }

            if ( $validate_type == '>=' ) {

                if ( $value === '' ) {

                    return false;
                }

                return ($value >= $rule_value);
            }
            if ( $validate_type == '>' ) {

                if ( $value === '' ) {


                    return false;
                }

                return ($value > $rule_value);
            }

            if ( $validate_type == '<=' ) {

                if ( $value === '' ) {

                    return false;
                }

                return ($value <= $rule_value);
            }

            if ( $validate_type == '<' ) {

                if ( $value === '' ) {

                    return false;
                }

                return ($value < $rule_value);
            }

            if ( $validate_type == '==' ) {

                return ($value == $rule_value);
            }

            if ( $validate_type == '!=' ) {

                return ($value != $rule_value);
            }

            if ( $validate_type == 'checked' ) {

                $is_empty = false;

                if ( $value == 'yes' ) {

                    $is_empty = true;
                }

                return $this->validate_yes_no( $is_empty, $rule_yes_no );
            }

            return false;
        }

        public function validate_value_list( $value, $rule_list, $validate_type ) {

            $found = in_array( $value, $rule_list );

            $is_equals = ('in_list' == $validate_type );

            return ($found == $is_equals);
        }

        public function validate_list_list( $list, $rule_list, $validate_type ) {

            if ( $validate_type == 'in_list' || $validate_type == 'none' ) {

                return $this->validate_list_in_list( $list, $rule_list, $validate_type );
            }

            if ( $validate_type == 'in_all_list' ) {

                return $this->validate_list_all_in_list( $list, $rule_list );
            }

            if ( $validate_type == 'in_list_only' ) {

                return $this->validate_list_only_in_list( $list, $rule_list );
            }

            if ( $validate_type == 'in_all_list_only' ) {

                $all_list = $this->validate_list_all_in_list( $list, $rule_list );

                $only_list = $this->validate_list_only_in_list( $list, $rule_list );

                return ($all_list == true && $only_list == true);
            }

            return false;
        }

        private function validate_list_in_list( $list, $rule_list, $validate_type ) {

            $found = false;

            $is_equals = ('in_list' == $validate_type );

            foreach ( $list as $lst ) {

                if ( true == $found ) {

                    break;
                }

                if ( $this->validate_value_list( $lst, $rule_list, 'in_list' ) ) {

                    $found = true;
                }
            }

            return ($found == $is_equals);
        }

        private function validate_list_all_in_list( $list, $rule_list ) {

            $found_count = 0;

            $rule_list_count = count( $rule_list );

            foreach ( $list as $lst ) {

                if ( $this->validate_value_list( $lst, $rule_list, 'in_list' ) ) {

                    $found_count++;
                }
            }

            return ($found_count == $rule_list_count);
        }

        private function validate_list_only_in_list( $list, $rule_list ) {

            $found_count = 0;

            $list_count = count( $list );

            foreach ( $rule_list as $lst ) {

                if ( $this->validate_value_list( $lst, $list, 'in_list' ) ) {

                    $found_count++;
                }
            }

            return ($found_count == $list_count);
        }

        public function validate_yes_no( $value, $rule_yes_no ) {

            $yes_value = 'no';

            if ( $value == true ) {

                $yes_value = 'yes';
            }

            return ($yes_value == $rule_yes_no);
        }

        private function starts_with( $needle, $haystack ) {

            $haystack_lower = strtolower( $haystack );
            $needle_lower = strtolower( $needle );

            return str_starts_with( $haystack_lower, $needle_lower );
        }

        private function ends_with( $needle, $haystack ) {

            $haystack_lower = strtolower( $haystack );
            $needle_lower = strtolower( $needle );

            return str_ends_with( $haystack_lower, $needle_lower );
        }

        private function contains( $needle, $haystack ) {

            $needle_lower = strtolower( $needle );
            $haystack_lower = strtolower( $haystack );

            return str_contains( $haystack_lower, $needle_lower );
        }

    }

}
