<?php
/**
 * User: 김국현
 * Date: 2021-04-04
 * Time: 오후 11:01
 */

// 문자열이 한글, 영문, 숫자, 특수문자로 구성되어 있는지 검사
function findRegexString(string $str, int $options): bool
{
    if (empty($str)) {
        return false;
    }

    $s = '';
    for ($i = 0; $i < strlen($str); $i++) {
        $c = $str[$i];
        $oc = ord($c);

        // 한글
        if ($oc >= 0xA0 && $oc <= 0xFF) {
            if (strtoupper(env('APP_CHARSET', 'UTF-8')) === 'UTF-8') {
                if ($options & _HANGUL_) {
                    $s .= $c . $str[$i + 1] . $str[$i + 2];
                }
                $i += 2;
            } else {
                // 한글은 2바이트 이므로 문자하나를 건너뜀
                $i++;
                if ($options & _HANGUL_) {
                    $s .= $c . $str[$i];
                }
            }
        } elseif ($oc >= 0x30 && $oc <= 0x39) { // 숫자
            if ($options & _NUMERIC_) {
                $s .= $c;
            }
        } elseif ($oc >= 0x41 && $oc <= 0x5A) { // 영대문자
            if (($options & _ALPHABETIC_) OR ($options & _ALPHAUPPER_)) {
                $s .= $c;
            }
        } elseif ($oc >= 0x61 && $oc <= 0x7A) { // 영소문자
            if (($options & _ALPHABETIC_) OR ($options & _ALPHALOWER_)) {
                $s .= $c;
            }
        } elseif ($oc >= 0x20) { // 공백
            if ($options & _SPACE_) {
                $s .= $c;
            }
        } elseif ($oc >= 0x5F) { // `_` 언더바

            if ($options & _UNDER_) {
                $s .= $c;
            }
        } else {
            if ($options & _SPECIAL_) {
                $s .= $c;
            }
        }
    }
    // 넘어온 값과 비교하여 같으면 참, 틀리면 거짓
    return ($str === $s);
}

// 문자열에 정규식을 적용하여 배열로 만든다.
function countOccurrences(string $str, string $exp): int
{
    preg_match_all($exp, $str, $match);
    return count($match[0]);
}

// 문자열에 소문자 개수가 몇개인지
function countLowercase(string $str): int
{
    return countOccurrences($str, '/[a-z]/');
}

// 문자열에 대문자 개수가 몇개인지
function countUppercase(string $str): int
{
    return countOccurrences($str, '/[A-Z]/');
}

// 문자열에 숫자 개수가 몇개인지
function countNumbers(string $str): int
{
    return countOccurrences($str, '/[0-9]/');
}

// 문자열에 특수문자 개수가 몇개인지
function countSpecialChars(string $str): int
{
    return countOccurrences($str, '/[!@#$%^&*()]/');
}

// 원하는 문자열을 원하는 길에 맞는지 확인해서 조정하는 기능을 합니다.
function cutChar(string $word, int $cut): string
{
    $word = substr($word, 0, $cut); // 필요한 길이만큼 취함.
    for ($k = $cut - 1; $k > 1; $k--) {
        if (ord(substr($word, $k, 1)) < 128) {
            break; // 한글값은 160 이상.
        }
    }
    return substr($word, 0, $cut - ($cut - $k + 1) % 2);
}

// UTF-8 자르기
function cutCharUtf8(string $word, int $cut, string $mask = '...'): string
{
    if($cut <= 0) {
        return $word;
    }

    preg_match_all('/[\xE0-\xFF][\x80-\xFF]{2}|./', $word, $match); // target for BMP

    $m = $match[0];
    $len = strlen($word); // length of source string
    if ($len <= $cut) {
        return $word;
    }

    $ret = [];
    $count = 0;
    for ($i = 0; $i < $cut; $i++) {
        $count += (strlen($m[$i]) > 1) ? 2 : 1;
        if ($count > $cut) {
            break;
        }
        $ret[] = $m[$i];
    }

    return (join('', $ret) . $mask);
}

// base encode 확인
function isBase64($s = ""): bool
{
    return (bool)preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s);
}

// 절대 경로 삭제 (../../../)
function canonicalizePath($path): string
{
    $path = array_filter(explode(DIRECTORY_SEPARATOR, $path));
    $stack = [];
    foreach ($path as $seg) {
        if ($seg == '..') {
            array_pop($stack);
            continue;
        }

        if ($seg == '.') {
            continue;
        }

        $stack[] = $seg;
    }

    return (DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $stack));
}

// alert 에서 php 개행이 되도록 예외처리 한다.
function nl2nr(string $s): string
{
    $s = preg_replace('/(\r\n|\r|\n)/', '\n', addslashes($s)); // 줄바꿈 되도록 출력
    $s = strip_tags(trim($s), '<br/>'); // 태그 제거, 공백 제거
    return preg_replace('/<br[^>]*>/i', '\n\n', $s); // br 태그를 \n로 개행 alert 에서 다음줄로 하기 위함.
}

// 휴대전화번호에 하이픈(-) 넣기
function addHyphen($tel): string
{
    $tel = preg_replace("/[^0-9]/", "", $tel);    // 숫자 이외 제거
    if (substr($tel, 0, 2) == '02') {
        return preg_replace("/([0-9]{2})([0-9]{3,4})([0-9]{4})$/", "\\1-\\2-\\3", $tel);
    } else if (strlen($tel) == '8' && (substr($tel, 0, 2) == '15' || substr($tel, 0, 2) == '16' || substr($tel, 0, 2) == '18')) {
        // 지능망 번호이면
        return preg_replace("/([0-9]{4})([0-9]{4})$/", "\\1-\\2", $tel);
    } else {
        return preg_replace("/([0-9]{3})([0-9]{3,4})([0-9]{4})$/", "\\1-\\2-\\3", $tel);
    }
}
