<?php

namespace platyFramework;

/**
 * refs https://github.com/alecgorge/PHP-String-Class/blob/master/string.php
 */

// why doesn't this function exist?
if (!function_exists('platyFramework\mb_str_replace')) {
    function mb_str_replace($search, $replace, $subject)
    {
        return preg_replace('@' . preg_quote($search) . '@u', $replace, $subject);
    }
}
if (!function_exists('platyFramework\mb_str_split')) {
    function mb_str_split($str, $length = 1)
    {
        preg_match_all('/.{1,' . $length . '}/us', $str, $matches);
        return $matches[0];
    }
}

class ptyArray extends \ArrayObject
{
    private static $ret_obj = true;

    public static function build($array = null)
    {
        $_this = new static ($array);
        return $_this;
    }

    public function get($i)
    {
        $val = $this->offsetGet($i);
        if (is_array($val)) {
            return new self($val);
        }
        if (is_string($val) && self::$ret_obj) {
            return new ptyString($val);
        }
        return $val;
    }

    public function each($callback)
    {
        foreach ($this as $key => $val) {
            call_user_func_array($callback, array(
                $val, $key, $this
            ));
        }
        return $this;
    }

    public function set($i, $v)
    {
        $this->offsetSet($i, $v);
        return $this;
    }

    public function push($value)
    {
        $this[] = $value;
        return $this;
    }

    public function join($paste = '')
    {
        return implode($paste, $this->getArrayCopy());
    }

    public function sort()
    {
        $this->asort();
        return $this;
    }

    public function toArray()
    {
        return $this->getArrayCopy();
    }

    public function _natsort()
    {
        parent::_natsort();
        return $this;
    }

    public function rsort()
    {
        parent::uasort('Arr::sort_alg');
        return $this;
    }

    public static function sort_alg($a, $b)
    {
        if ($a == $b) {
            return 0;
        }
        return ($a < $b) ? 1 : -1;
    }

    public function pdf($title = "")
    {
        pdf($this, $title);
    }

    public function pdf1($title = "")
    {
        $out = "";
        // 객체 배열 출력
        foreach ($this as $index => $obj) {
            // _item 배열에 접근
            $item = $obj->_item; // 객체의 _item 속성
            $out .= "[{$index}] ";
            foreach ($item as $key => $value) {
                $out .= "{$key} = {$value}, ";
            }
            $out .= PHP_EOL; // 줄바꿈
        }
        pdf($out, $title);
    }

    public function pdf2($title = "")
    {
        // [index]의 최대 길이 계산
        $maxIndexLength = 0;
        foreach ($this as $index => $obj) {
            $indexLength = strlen("[{$index}]");
            if ($indexLength > $maxIndexLength) {
                $maxIndexLength = $indexLength;
            }
        }

        // 모든 데이터에서 각 키의 최대 너비 계산
        $fieldWidths = [];
        foreach ($this as $obj) {
            $item = $obj->_item;
            foreach ($item as $key => $value) {
                $length = strlen("{$key} = {$value}");
                if (!isset($fieldWidths[$key]) || $length > $fieldWidths[$key]) {
                    $fieldWidths[$key] = $length;
                }
            }
        }

        // 객체 배열 출력
        foreach ($this as $index => $obj) {
            $item = $obj->_item; // 객체의 _item 속성

            // [index] 부분 패딩
            $out .= str_pad("[{$index}]", $maxIndexLength + 1); // +1은 공백 여유

            foreach ($item as $key => $value) {
                // 각 필드의 너비에 맞춰 패딩
                $width = $fieldWidths[$key] ?? 20; // 계산된 너비 사용
                $out .= str_pad("{$key} = {$value}", $width);

                $out .= ", ";
            }
            $out .= PHP_EOL; // 줄바꿈
        }

        // PDF 생성 함수 호출
        pdf($out, $title);
    }

    public function pdf3($title = "", $rowsPerPage = 30, $useColors = false, $useFormatting = true)
    {
        $out = "";
        $rowCount = 0; // 행 카운터

        // 색상 정의
        $colors = [
            'header' => $useColors ? "\033[1;34m" : "", // 밝은 파란색
            'index' => $useColors ? "\033[1;32m" : "", // 밝은 녹색
            'reset' => $useColors ? "\033[0m" : "",    // 색상 초기화
        ];

        // [index]의 최대 길이 계산
        $maxIndexLength = 0;
        foreach ($this as $index => $obj) {
            $indexLength = strlen("{$index}");
            if ($indexLength > $maxIndexLength) {
                $maxIndexLength = $indexLength;
            }
        }
        $maxIndexLength++;

        // 모든 데이터에서 각 키의 최대 너비 계산
        $fieldWidths = [];
        foreach ($this as $obj) {
            if ($obj instanceof ptyArrayItemModel) {
                $item = $obj->_item; // 객체의 _item 속성
            } else {
                $item = $obj;
            }

            foreach ($item as $key => $value) {
                $length = max(strlen($key), strlen($useFormatting ? $this->formatValue($value) : (string)$value));
                if (!isset($fieldWidths[$key]) || $length > $fieldWidths[$key]) {
                    $fieldWidths[$key] = $length;
                }
            }
        }

        // 헤더 생성 함수
        $createHeader = function () use ($fieldWidths, $maxIndexLength, $colors) {
            $header = $colors['header'] . str_pad("IDX", $maxIndexLength) . " | ";
            foreach ($fieldWidths as $key => $width) {
                $header .= str_pad($key, $width) . " | ";
            }
            $header .= $colors['reset'] . PHP_EOL;
            $header .= str_repeat("-", strlen(strip_tags($header))) . PHP_EOL;
            return $header;
        };

        // 첫 번째 헤더 추가
        $out .= $createHeader();

        // 데이터 출력 (index 포함)
        foreach ($this as $index => $obj) {
            $rowCount++;

            if ($obj instanceof ptyArrayItemModel) {
                $item = $obj->_item; // 객체의 _item 속성
            } else {
                $item = $obj;
            }

            // $rowsPerPage 행마다 헤더 다시 출력
            if ($rowsPerPage > 0 && $rowCount % $rowsPerPage === 0) {
                $out .= $createHeader();
            }

            // 데이터 행 작성
            $row = $colors['index'] . str_pad("{$index}", $maxIndexLength) . " | " . $colors['reset'];
            foreach ($fieldWidths as $key => $width) {
                $value = $item[$key] ?? ""; // 키가 없는 경우 빈 값
                $row .= str_pad($useFormatting ? $this->formatValue($value) : (string)$value, $width) . " | ";
            }
            $out .= $row . PHP_EOL;
        }

        // PDF 생성 함수 호출
        pdf($out, $title);
    }

    /**
     * 데이터 타입에 따라 값을 포맷팅합니다.
     */
    private function formatValue($value)
    {
        if (is_int($value)) {
            return "{$value} (int)";
        } elseif (is_float($value)) {
            return "{$value}(float)";
        } elseif (is_bool($value)) {
            return "{$value} (bool)";
        } elseif (is_null($value)) {
            return "(NULL)";
        } elseif (is_string($value)) {
            return "{$value}";
        }
        // string이나 기타 값은 그대로 반환
        return "{$value}";
    }

    function getPrintTable($s = null, $title = "", string $primaryLabel = "날짜", $rowsPerPage = 150, $useColors = false, $showFormatting = false)
    {
        $out = "";
        $rowCount = 0; // 행 카운터

        // 색상 정의
        $colors = [
            'header' => $useColors ? "\033[1;34m" : "", // 밝은 파란색
            'index' => $useColors ? "\033[1;32m" : "", // 밝은 녹색
            'reset' => $useColors ? "\033[0m" : "",    // 색상 초기화
        ];

        // [index]의 최대 길이 계산
        $maxIndexLength = 0;
        foreach ($s as $index => $obj) {
            $indexLength = strlen("{$index}");
            if ($indexLength > $maxIndexLength) {
                $maxIndexLength = $indexLength;
            }
        }
        $maxIndexLength++;

        // 모든 데이터에서 각 키의 최대 너비 계산
        $fieldWidths = [];
        foreach ($s as $obj) {
            if ($obj instanceof \platyFramework\ptyArrayItemModel) {
                $item = $obj->_item; // 객체의 _item 속성
            } else {
                $item = $obj;
            }

            foreach ($item as $key => $value) {
                $length = max(strlen($key), strlen($showFormatting ? formatTypeValue($value) : (string)$value));
                if (!isset($fieldWidths[$key]) || $length > $fieldWidths[$key]) {
                    $fieldWidths[$key] = $length;
                }
            }
        }

        // 헤더 생성 함수
        $createHeader = function () use ($primaryLabel, $fieldWidths, $maxIndexLength, $colors) {
            $header = $colors['header'] . str_pad($primaryLabel, $maxIndexLength) . " | ";
            foreach ($fieldWidths as $key => $width) {
                $header .= str_pad($key, $width) . " | ";
            }
            $header .= $colors['reset'] . PHP_EOL;
            $header .= str_repeat("-", strlen(strip_tags($header))) . PHP_EOL;
            return $header;
        };

        // 첫 번째 헤더 추가
        $out .= $createHeader();

        // 데이터 출력 (index 포함)
        foreach ($s as $index => $obj) {
            $rowCount++;

            if ($obj instanceof \platyFramework\ptyArrayItemModel) {
                $item = $obj->_item; // 객체의 _item 속성
            } else {
                $item = $obj;
            }

            // $rowsPerPage 행마다 헤더 다시 출력
            if ($rowsPerPage > 0 && $rowCount % $rowsPerPage === 0) {
                $out .= $createHeader();
            }

            // 데이터 행 작성
            $row = $colors['index'] . str_pad("{$index}", $maxIndexLength) . " | " . $colors['reset'];
            foreach ($fieldWidths as $key => $width) {
                $value = $item[$key] ?? ""; // 키가 없는 경우 빈 값
                $row .= str_pad($showFormatting ? formatTypeValue($value) : (string)$value, $width) . " | ";
            }
            $out .= $row . PHP_EOL;
        }

        // PDF 생성 함수 호출
        return $out;
    }


}

?>
