<?php

namespace Linksy\SearchAndReplace\Plugli\Standard\Helpers;

/**
 * Handle Strings.
 *
 * @since      1.0.0
 * @package    Plugli
 * @subpackage Plugli/Standard/Helpers
 * @author     Plugli <https://plugli.com>
 */
/**
 * String class.
 */
class Str
{
    public static function word_count($string)
    {
        return sizeof(explode(" ", $string));
    }
    public static function strip_tags($string)
    {
        $replace = [['<div', '<br', '<li', '<p', '<h1', '<h2', '<h3', '<h4', '<h5', '<h6'], ["\n<div", "\n<br", "\n<li", "\n<p", "\n<h1", "\n<h2", "\n<h3", "\n<h4", "\n<h5", "\n<h6"]];
        $string = str_ireplace($replace[0], $replace[1], $string);
        $string = preg_replace('|\.([A-Z]{1})|', ".\n\$1", $string);
        $string = preg_replace('|\[[^\]]+\]|i', "\n", $string);
        // from wp_strip_all_tags
        $string = preg_replace('@<(script|style)[^>]*?>.*?</\1>@si', '', $string);
        $string = preg_replace('/\s+/', ' ', $string);
        return strip_tags(trim($string));
    }
    public static function strip_comments($content)
    {
        return preg_replace('/<!--(.*?)-->/s', '', $content) ?? '';
    }
    public static function strip_emojis($string)
    {
        // Match Enclosed Alphanumeric Supplement
        $regex_alphanumeric = '/[\x{1F100}-\x{1F1FF}]/u';
        $clear_string = preg_replace($regex_alphanumeric, '', $string);
        // Match Miscellaneous Symbols and Pictographs
        $regex_symbols = '/[\x{1F300}-\x{1F5FF}]/u';
        $clear_string = preg_replace($regex_symbols, '', $clear_string);
        // Match Emoticons
        $regex_emoticons = '/[\x{1F600}-\x{1F64F}]/u';
        $clear_string = preg_replace($regex_emoticons, '', $clear_string);
        // Match Transport And Map Symbols
        $regex_transport = '/[\x{1F680}-\x{1F6FF}]/u';
        $clear_string = preg_replace($regex_transport, '', $clear_string);
        // Match Supplemental Symbols and Pictographs
        $regex_supplemental = '/[\x{1F900}-\x{1F9FF}]/u';
        $clear_string = preg_replace($regex_supplemental, '', $clear_string);
        // Match Miscellaneous Symbols
        $regex_misc = '/[\x{2600}-\x{26FF}]/u';
        $clear_string = preg_replace($regex_misc, '', $clear_string);
        // Match Dingbats
        $regex_dingbats = '/[\x{2700}-\x{27BF}]/u';
        $clear_string = preg_replace($regex_dingbats, '', $clear_string);
        // illumiish
        $regex_illuminish = '/[\x{13080}-\x{13089}]/u';
        $clear_string = preg_replace($regex_illuminish, '', $clear_string);
        return $clear_string;
    }
    public static function strip_unicode($string)
    {
        $special_chars = '%81,%7F,%8D,%8F,%C2%90,%C2,%90,%9D,%C2%A0,%A0,%C2%AD,%AD,%08,%09,%0A,%0D';
        $special_chars_array = explode(',', $special_chars);
        $string = urlencode($string);
        foreach ($special_chars_array as $v) {
            $string = str_replace($v, ' ', $string);
        }
        $string = urldecode($string);
        return $string;
    }
    public static function strip_quotes($string)
    {
        if (substr($string, 0, 1) == '"' || substr($string, 0, 1) == "'") {
            $string = substr($string, 1);
        }
        if (substr($string, -1) == '"' || substr($string, -1) == "'") {
            $string = substr($string, 0, -1);
        }
        return $string;
    }
    public static function addSlashToUnicodeSequences($string)
    {
        $pattern = '/\\\\u([0-9a-fA-F]{4})/';
        $replacement = '\\\\$0';
        return preg_replace($pattern, $replacement, $string);
    }
    public static function is_in_comment($content, $str)
    {
        return preg_match('/<!--[^>]*' . preg_quote($str, '/') . '[^>]*-->/', $content);
    }
    public static function get_enclosing_tag($content, $str)
    {
        $dom = new \DOMDocument();
        // Load the HTML content into the DOMDocument
        @$dom->loadHTML($content, \LIBXML_HTML_NOIMPLIED | \LIBXML_HTML_NODEFDTD);
        $xpath = new \DOMXPath($dom);
        // Escape special characters in the search string for XPath
        $str = htmlspecialchars($str, \ENT_QUOTES, 'UTF-8');
        // Find all elements containing the substring
        $elements = $xpath->query("//*[contains(text(), '{$str}')]") ?? [];
        // Find all comments containing the substring
        $comments = $xpath->query("//comment()[contains(., '{$str}')]") ?? [];
        if ($elements->length > 0) {
            $element = $elements->item(0);
            $tagName = $element->nodeName;
            return $tagName;
        } elseif ($comments->length > 0) {
            return "<!>";
        }
        return null;
    }
    public static function remove_enclosing_tags($html)
    {
        // Match the outermost opening and closing tags and their content
        preg_match('/^<([a-zA-Z0-9]+)[^>]*>(.*)<\/\1>$/s', $html, $matches);
        // If no match is found, return the original HTML
        if (!$matches) {
            return $html;
        }
        // Return the inner content
        return self::remove_enclosing_tags($matches[2]);
    }
    public static function delete_tags($string, $tags)
    {
        foreach ($tags as $tag) {
            $pattern = "/<{$tag}[^>]*>(.*?)<\\/{$tag}>|<{$tag}[^>]*\\/?>/is";
            while (preg_match($pattern, $string)) {
                $string = preg_replace($pattern, '', $string);
            }
        }
        return $string;
    }
    public static function text_to_paragraphs($content)
    {
        $replace_unicode = array(['\u003c', '\u003e', '\u0022', '&nbsp;'], ['<', '>', '"', ' ']);
        $content = str_ireplace($replace_unicode[0], $replace_unicode[1], $content);
        $replace = [['<div', '<br', '<li', '<p', '<h1', '<h2', '<h3', '<h4', '<h5', '<h6'], ["\n<div", "\n<br", "\n<li", "\n<p", "\n<h1", "\n<h2", "\n<h3", "\n<h4", "\n<h5", "\n<h6"]];
        $content = str_ireplace($replace[0], $replace[1], $content);
        $content = preg_replace('|\.([A-Z]{1})|', ".\n\$1", $content);
        $content = preg_replace('|\[[^\]]+\]|i', "\n", $content);
        $output = [];
        $sentences = explode("\n", $content);
        foreach ($sentences as $key => $sentence) {
            if (empty($sentence)) {
                continue;
            }
            // remove empty tags
            if (empty(trim(strip_tags($sentence)))) {
                continue;
            }
            // remove comments
            if (substr($sentence, 0, 4) == '<!--' && substr($sentence, -3) == '-->') {
                continue;
            }
            // todo: remove numbering
            // remove empty
            $sentence = trim($sentence);
            if (empty($sentence) || $sentence == "") {
                continue;
            }
            $output[] = $sentence;
        }
        return $output;
    }
    public static function text_to_sentences($content, $preserve_punctuation = \false, $min_length = 1)
    {
        $content = trim($content);
        // strip off the following special characters when not preserving punctuation
        if (!$preserve_punctuation && in_array(substr($content, -1), ['.', '!', '?', "\n"])) {
            $content = trim(substr($content, 0, -1));
        }
        if (empty($content) || str_word_count($content) < $min_length) {
            return [];
        }
        $replace = [".\r", '. ', '!', '?'];
        //[', ', ': ', '; ', ' – ', ' (', ') ', ' {', '} ', '—', '”'];
        //change divided symbols inside tags to special codes
        preg_match_all('|<[^>]+>|', $content, $matches);
        if (!empty($matches[0])) {
            foreach ($matches[0] as $tag) {
                $tag_replaced = $tag;
                foreach ($replace as $key => $value) {
                    if (strpos($tag, $value) !== \false) {
                        $tag_replaced = str_replace($value, "[rp{$key}]", $tag_replaced);
                    }
                }
                if ($tag_replaced != $tag) {
                    $content = str_replace($tag, $tag_replaced, $content);
                }
            }
        }
        if ($preserve_punctuation) {
            // add new line character to the replaceable punctuation characters.
            $content = str_ireplace($replace, [".\r\n", ".\n", "!\n", "?\n"], $content);
        } else {
            // replace punctuation characters with newline character
            $content = str_ireplace($replace, "\n", $content);
        }
        //change special codes to divided symbols inside tags
        foreach ($replace as $key => $value) {
            $content = trim(str_replace("[rp{$key}]", $value, $content));
        }
        return array_filter(explode("\n", $content), function ($phrase) use ($min_length) {
            return str_word_count($phrase) > $min_length;
        });
    }
    public static function text_to_words($content)
    {
        return array_map(function ($phrase) {
            return trim(preg_replace('/\s+/', ' ', $phrase));
        }, explode(" ", $content));
    }
    public static function position($content, $str, $whole_word = \false)
    {
        if (empty($content) || empty($str)) {
            return \false;
        }
        if ($whole_word) {
            if (preg_match('#\b' . preg_quote($str, '#') . '\b#i', $content) !== 1) {
                return \false;
            }
        }
        return strpos(strtolower($content), strtolower($str));
    }
    public static function contains($content, $str, $whole_word = \false)
    {
        return self::position($content, $str, $whole_word) !== \false;
    }
    public static function compare($a, $b, $key, $dir)
    {
        if ($dir == 'desc') {
            $temp = $a;
            $a = $b;
            $b = $temp;
        }
        if ($a[$key] == $b[$key]) {
            return 0;
        }
        return $a[$key] < $b[$key] ? -1 : 1;
    }
    public static function indent_dom($content, $tab = "\t")
    {
        // adds a linefeed between all tag-end boundaries
        $content = preg_replace('/(>)(<)(\/*)/', "\$1\n\$2\$3", $content);
        $token = strtok($content, "\n");
        $result = '';
        $pad = $indent = 0;
        $voidTag = \false;
        $matches = [];
        // scan each line and adjust indent based on opening/closing tags
        while ($token !== \false && strlen($token) > 0) {
            $token = trim($token);
            // test for the various tag states
            if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) {
                // 1. open and closing tags on same line - no change
                $indent = 0;
            } elseif (preg_match('/^<\/\w/', $token, $matches)) {
                // 2. closing tag - outdent now
                $pad--;
                if ($indent > 0) {
                    $indent = 0;
                }
            } elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) {
                // 3. don't pad void tags
                foreach ($matches as $m) {
                    // Void elements according to http://www.htmlandcsswebdesign.com/articles/voidel.php
                    if (preg_match('/^<(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)/im', $m)) {
                        $voidTag = \true;
                        break;
                    }
                }
                $indent = 1;
            } else {
                // 4. no indentation needed
                $indent = 0;
            }
            if ($token == "<textarea>") {
                $line = str_pad($token, strlen($token) + $pad, $tab, \STR_PAD_LEFT);
                $result .= $line;
                $token = strtok("\n");
                $pad += $indent;
            } elseif ($token == "</textarea>") {
                $line = $token;
                $result .= $line . "\n";
                $token = strtok("\n");
                $pad += $indent;
            } else {
                $line = str_pad($token, strlen($token) + $pad, $tab, \STR_PAD_LEFT);
                $result .= $line . "\n";
                // add to the cumulative result, with linefeed
                $token = strtok("\n");
                $pad += $indent;
                if ($voidTag) {
                    $voidTag = \false;
                    $pad--;
                }
            }
        }
        return $result;
    }
    public static function protrude_dom($content, $tab = "\t")
    {
        return trim(str_replace($tab, "", $content));
    }
}
