<?php
use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Cell\DataType;

class common
{
     /* Session data 영역 시작 */
     function setSession($id, $password, $company, $department, $displayname, $Position, $operatorUID) {
          $_SESSION["ID"] = $id;
          $_SESSION["Password"] = $password;
          $_SESSION["Company"] = $company;
          $_SESSION["Department"] = $department;
          $_SESSION["DisplayName"] = $displayname;
          $_SESSION["Position"] = $Position;
          //$_SESSION["ExpiredDate"] = strtotime("+18000 second");
          $_SESSION["ExpiredDate"] = strtotime("+2400 second");
          $_SESSION["OperatorUID"] = $operatorUID;
     }

     function setSessionServerType($serverType) {
          $_SESSION["ServerType"] = $serverType;
     }

     /* Session data 영역 시작 */
     function refreshSession() {
         $_SESSION["ID"] = $_SESSION["ID"] ?? '';
         $_SESSION["Password"] = $_SESSION["Password"] ?? '';
         $_SESSION["Company"] = $_SESSION["Company"] ?? '';
         $_SESSION["Department"] = $_SESSION["Department"] ?? '';
         $_SESSION["DisplayName"] = $_SESSION["DisplayName"] ?? '';
         $_SESSION["Position"] = $_SESSION["Position"] ?? '';
         $_SESSION["ExpiredDate"] = strtotime("+2400 second");
         $_SESSION["OperatorUID"] = $_SESSION["OperatorUID"] ?? '';
     }

     function refreshSessionServerType() {
         $_SESSION["ServerType"] = $_SESSION["ServerType"] ?? '';
     }

     static function getOperatorUID() {
          return $_SESSION["OperatorUID"] ?? null;
     }

     function checkSession($checkFlag, $container) {
          if (false == $checkFlag) {
               return true;
          }

          $serverType = $this->getServerName($container);
          if (isset($_SESSION['ServerType'])) {
               if ($_SESSION['ServerType'] != $serverType) {
                    $this->destroySession();
                    return false;
               }
          }

          if (isset($_SESSION['ExpiredDate']) && $_SESSION['ExpiredDate'] >= time()) {
               return true;
          }

          return false;
     }

     function getPermission($operatorUID = NULL) {
         $chkOperatorUID = ($operatorUID) ? $operatorUID : common::getOperatorUID();
         return $this->getUserPermission($chkOperatorUID);
     }

     function checkPermission($conn, $authority) {
          $result = false;

          $operatorUID = $_SESSION["OperatorUID"];

          $data = $this->getPermission($operatorUID);
          if (0 < $data['Code'] && null != $data['Data']) {            
               foreach ($data['Data'] as $key => $value) {
                    if ($authority == $key && 0 < $value['Authority']) {
                         $result = true;
                         $status = $value['Authority'];
                         break;                                  
                    }                  
               }
          }

          $_SESSION["MenuID"] = $authority;
          if (true == $result) $_SESSION["MenuStatus"] = $status;         
          else $_SESSION["MenuStatus"] = enum::AUTH_MENU_PERMISSION_NONE;
                                        
          return $result;
     }

     function checkPermission_write($checkFlag) {
          if (false == $checkFlag) {         
               return true;
          }

          $result = false;
          $status = $_SESSION["MenuStatus"];

          switch($status) {
               case enum::AUTH_MENU_PERMISSION_WRITE :
               {
                    $result = true;
               }
               break;
          }
     
          return $result;
     }

     function checkPermission_admin($adinfo) {
          $result = false;
          if (in_array($adinfo['OperationUID'], enum::ADMIN_SUPER_ID)) {
               $result = true;
          }
 
          return $result;
     }

     function destroySession() {
          session_destroy();
     }

     static function isJsonRequest($request) {
          $result = FALSE;
          $contentType = $request->getContentType();
          if (!empty($contentType)) {
               $result = strpos(strtolower($contentType),'json') !== FALSE;
          }
         return $result;
     }

     function getProfile(&$resData) {
          $resData['Company'] = isset($_SESSION["Company"]) ? $_SESSION["Company"] : "onbuff";
          $resData['Department'] = isset($_SESSION["Department"]) ? $_SESSION["Department"] : "admin";
          $resData['DisplayName'] = isset($_SESSION["DisplayName"]) ? $_SESSION["DisplayName"] : "admin";
          $resData['Position'] = isset($_SESSION["Position"]) ? $_SESSION["Position"] : "admin";
          $resData['IsLogin'] = true;
          $resData['OperatorUID'] = isset($_SESSION["OperatorUID"]) ? $_SESSION["OperatorUID"] : "admin";
     }

     function getUserInfo() {
          $result = array();
          $result['Company'] = isset($_SESSION["Company"]) ? $_SESSION["Company"] : "onbuff";
          $result['Department'] = isset($_SESSION["Department"]) ? $_SESSION["Department"] : "admin";
          $result['DisplayName'] = isset($_SESSION["DisplayName"]) ? $_SESSION["DisplayName"] : "admin";
          $result['Position'] = isset($_SESSION["Position"]) ? $_SESSION["Position"] : "admin";
          $result['ID'] = isset($_SESSION["ID"]) ? $_SESSION["ID"] : "0";
          $result['OperatorUID'] = isset($_SESSION["OperatorUID"]) ? $_SESSION["OperatorUID"] : "admin";

          return $result;
     }

     function setCommonData(&$resData, $request, $container) {
          // MenuSetting
          $resData['adminMenu'] = $container->menu;
          $menus = $container->menu->getCurrentBreadCrumbs();
          $breadcrumbs = "";
          if (is_array($menus)) {
              foreach ($menus as $key => $menu) {
                    $breadcrumbs .= $menu['text'];
                    // if($key > 0) $breadcrumbs .= " &gt; ";
                    if($key > 0) $breadcrumbs .= " / ";
              }
          }
          $resData['breadcrumbs'] = $breadcrumbs;

          // html 태그 추가된 버전
          $breadcrumbsTag = "";
          if (is_array($menus)) {
              foreach ($menus as $key => $menu) {
                    $breadcrumbsTag .= $menu['text'];
                    if ($key > 0) $breadcrumbsTag = "<span class=\"text-muted fw-light\">" . $breadcrumbsTag . " &gt; </span>";
              }
          }
          // <span class="text-muted fw-light">Tables /</span>
          $resData['breadcrumbsTag'] = $breadcrumbsTag;

          $cdn = $container->cdn;           
          $resData['CDN'] = $cdn['default'];
          $resData['style'] = $cdn['style'];
          $storage = $container->storage;
          $resData['storageURL'] = $storage['url'];

          $osname = php_uname();
          $osnameArray = explode(" ", $osname);

          $resData['osname'] = $osnameArray[0];
          $resData['adminType'] = strtoupper($this->getServerName($container));
          
          $resData['port'] = $_SERVER["SERVER_PORT"];

          $isLogin = false;
          $isSuperAdmin = false;
          if (isset($_SESSION["ID"])) {
               if ($_SESSION["ID"] != '') {
                    $isLogin = true;
                    if (in_array($_SESSION["ID"], enum::ADMIN_SUPER_ID)) {
                         $isSuperAdmin = true;
                    }
               }
          }
          $resData['isLogin'] = $isLogin;
          $resData['isSuperAdmin'] = $isSuperAdmin;
     }

     // function setCookie(&$resData, $request, $container)
     // {
     //       //LanguageSetting
     //       $localization = $container->get('settings')['localization'] ?? [];
     //       $resData['acceptLanguages'] = $localization['acceptLanguages'] ?? [];
     //       $resData['currentLanguage'] = $request->getAttribute($localization['languageParamName']);
     //       $resData['languageParamName'] = $localization['languageParamName'] ?? 'lang';
 
     //       //currentLanguage 존재할때 직접 세팅
     //       $params = $request->getParsedBody();
     //       if(isset($params['lang']))
     //            $resData['currentLanguage'] = $params['lang'];
     //   }

     function getPageInfo() {
          if (!isset($_SESSION)) {
               session_start();
          }

          $result = array();
          $result['MenuID'] = $_SESSION["MenuID"];
          $result['DisplayName'] = $_SESSION["DisplayName"];
          $result['Department'] = $_SESSION["Department"];
          $result['OperatorUID'] = $_SESSION["OperatorUID"];

          return $result;
     }


     /*
     Type : Platform 타입
     Server : {} 서버 정보 + 어플리케이션 정보 (필요에 따라 변경 가능)
     Time : 발생 시간 (yyyy-MM-dd HH:mm:ss.ff)
     선택 정보
     Data : {} 해당 로그 타입에 필요한 정보들
     ============================================================
     return : 1 or 0
     desc : 부가 정보
     */
     function sendLogReceiver($cmd, $ip, $value) {
          $sendMsg = array();

          $sendMsg['Type'] = $cmd;
          $sendMsg['Server']['Addr'] = $_SERVER['SERVER_ADDR'];
          $sendMsg['Server']['name'] = "MPBS";
          $sendMsg['Server']['stage'] = getServerType();
          $sendMsg['Time'] = date('Y-m-d H:i:s', time()); 
          $sendMsg['Data'] = array();
                    
          switch($cmd) {
               case enum::LOGRECEIVER_PLATFORMTYPE_MPBS_LOGLIST :
                    {
                         //로그 리스트 변경
                         $sendMsg['Data']['LogList'] = $value;
                    }
                    break;

               case enum::LOGRECEIVER_PLATFORMTYPE_MPBS_CHANGESTATE :
                    {
                         //머신 상태값 변경
                         $sendMsg['Data']['ChangeState'] = $value;
                    }
                    break;

               case enum::LOGRECEIVER_PLATFORMTYPE_MPBS_DELETECHANNEL :
                    {
                         //머신 상태값 변경
                         $sendMsg['Data']['DeleteChannelList'] = $value;
                    }
                    break;   
                    
               case enum::LOGRECEIVER_PLATFORMTYPE_MPBS_CHANGEALARM :
                    {
                         //머신 상태값 변경
                         $sendMsg['Data']['ChannelList'] = $value;
                    }
                    break;                      
          }

          $headers = array( "content-type: application/json", "accept-encoding: gzip", "charset: utf-8" );
          $sendUrl = "http://".$ip."/Platform";          
          //$sendUrl = "http://172.20.8.39:8080/Platform"; 
          //$test = json_encode($sendMsg);

          //CURL함수 사용 
          $curl=curl_init(); 
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
          curl_setopt($curl, CURLOPT_URL, $sendUrl); 
          //header값 셋팅(없을시 삭제해도 무방함) 
          curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); 
          //POST방식 
          curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); 
          curl_setopt($curl, CURLOPT_POST, true); 
          //POST방식으로 넘길 데이터(JSON데이터) 
          curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($sendMsg)); 
          
          //curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); 
          //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);   
          curl_setopt($curl, CURLOPT_TIMEOUT, 2);

          $response = curl_exec($curl); 
          
          if(curl_error($curl)) { 
               $curl_data = null; 
          } 
          else { 
               $curl_data = $response; 
          }

          curl_close($curl);
          
          $result = enum::LOGRECEIVER_NOT_CONNECT;

          //return data
          $json_data = json_decode($curl_data, true);
          
          if(false == is_null($json_data['result'])) $result = $json_data['result'];

          return $result;
     }
    
     function sendLog($container, $logType, $log) {
          //페이지 정보
          $pageInfo = $this->getPageInfo();

          $log['input']['menuID'] = $pageInfo['MenuID'];
          $log['input']['operatorUID'] = $pageInfo['OperatorUID'];
          $log['input']['operatorName'] = $pageInfo['DisplayName'];
          
          $container->logger->debug($logType, $log);
          return true;
     }

     function csvToJson($filePath) {
          //$filePath = "../table/".$fname.".csv";
          // open csv file
          if (!($fp = fopen($filePath, 'r'))) {
               return null;
          }
          
          //read csv headers
          $key = fgetcsv($fp,"1024",",");
          
          // parse csv rows into array
          $json = array();
          while ($row = fgetcsv($fp,"1024",",")) {
               $json[] = array_combine($key, $row);
          }
          
          // release file handle
          fclose($fp);
          $rtData['key'] = $key;
          $rtData['data'] = $json;
          // encode array to json
          return $rtData;
     }

     function httpcall($method, $url, $params, $header = []) {
          try {
               $curl = curl_init();
            
               switch($method) {
                    case 'post' :
                         curl_setopt($curl, CURLOPT_POST, true);
                         if (count($header) == 0) {
                              curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
                         }
                         else {
                              curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
                         }
                         $json = json_encode($params, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                         curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
                         break;
                    case 'put' :
                         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
                         if (count($header) == 0) {
                              curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
                         }
                         else {
                              curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
                         }
                         $json = json_encode($params, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                         curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
                         curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
                         break;
                    case 'patch' :
                         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');
                         if (count($header) == 0) {
                              curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
                         }
                         else {
                              curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
                         }
                         $json = json_encode($params, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                         curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
                         break;
                    case 'delete' :
                         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
                         $url = $url . '?' . http_build_query($params);
                         break;
                    case 'get' :
                         $url = $url . '?' . http_build_query($params);
                         break;                    
                    default :
                         break;
               }
               curl_setopt($curl, CURLOPT_URL, $url);
               curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
               curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
               curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
               curl_setopt($curl, CURLOPT_TIMEOUT, 30);
               $server_output = curl_exec($curl);
               curl_close ($curl);

               if ($server_output) {
                    $result = json_decode($server_output, true);
                    return $result;
               }
          }
          catch(Exception $e) {
               $result['return'] = $e->getCode();
               $result['message'] = $e->getMessage();
               return $result;
          }
     }

     function getGoogleSheets($sheetId, $sheetname) {
          $result = array();
          $result['Code'] = -1;
          try {
               $client = new Google_Client();
               $client->setApplicationName("common_spreadsheet");
               $client->setScopes(Google_Service_Sheets::SPREADSHEETS);
               $client->setAccessType('offline');
               $path = __DIR__ . '/../../credentials/google.json';
               $client->setAuthConfig($path);
               $service = new Google_Service_Sheets($client);
               //$range = 'MPBS!A3:D500';
               $response = $service->spreadsheets_values->get($sheetId, $sheetname);
               $result['Data'] = $response->getValues();  
               $result['Code'] = 200;
          }
          catch(Exception $e) {
               $result['Code'] = $e->getCode();
               $result['Msg'] = $e->getMessage();
          }
          return $result;
     }

     // function aes128Encrypt($str) {
     function aes128Encrypt($str, $key, $iv) {
          // $key = "wemade!@34";
          $cipher = "AES-128-CBC";
          // $iv = "2134567890123456";
          $encrypted_data = openssl_encrypt($str, $cipher, $key, 0, $iv);

          return $encrypted_data;
     }
     
     // function aes128Decrypt($data) {
     function aes128Decrypt($data, $key, $iv) {
          // $key = "wemade!@34";
          $cipher = "AES-128-CBC";
          // $iv = "2134567890123456";
          $decrypted_data = openssl_decrypt($data, $cipher, $key, 0, $iv);
          return $decrypted_data;
     }     

     static function uuid() {
         // https://www.php.net/manual/en/function.com-create-guid.php#117893
         //        if (function_exists('com_create_guid') === true)
         //            return trim(com_create_guid(), '{}');

         $data = PHP_MAJOR_VERSION < 7 ? openssl_random_pseudo_bytes(16) : random_bytes(16);
         $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
         $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
         return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
     }

     function ipfs_add($fileFullPath) {
          $osname = $this->get_os();
          if($osname == 'Windows') {
               $command = __DIR__.'\\..\\..'.enum::TOKENURI_PATH.'/ipfs.exe add '. $fileFullPath;
          }
          elseif($osname == 'Linux') {
               $command = '..'.enum::TOKENURI_PATH.'/ipfs_linux add '. $fileFullPath.' 2>&1';
          }
          elseif($osname == 'Darwin') {
               $command = '..'.enum::TOKENURI_PATH.'/ipfs add '. $fileFullPath;
          }
          $shell_result = shell_exec($command);
          $shell_result_array = explode(" ", $shell_result);
          foreach ($shell_result_array as $key => $val) {
               if (substr($val, -5) == 'added') {
                    return $shell_result_array[$key+1];
                    break;
               }
          }
          /*
          if($shell_result_array[0] == 'added'){
               return $shell_result_array[1];
          }else{
               return false;
          }
          */
     }

     function ipfs_pin($hash) {
          $osname = $this->get_os();
          if($osname == 'Windows') {
               $command = __DIR__.'\\..\\..'.enum::TOKENURI_PATH.'/ipfs.exe pin add '. $hash;
          }
          elseif($osname == 'Linux') {
               $command = '..'.enum::TOKENURI_PATH.'/ipfs_linux pin add '. $hash.' 2>&1';
          }
          elseif($osname == 'Darwin') {
               $command = '..'.enum::TOKENURI_PATH.'/ipfs pin add '. $hash;
          }          
          
          $shell_result = shell_exec($command);
          $shell_result_array = explode(" ", $shell_result);
          foreach ($shell_result_array as $key => $val) {
               if ($val == 'pinned' && $shell_result_array[$key+2] == 'recursively'.chr(10)) {
                    return $shell_result_array[$key+1];
                    break;
               }
          }
          return false;
          /*
          if($shell_result_array[0] == 'pinned' && $shell_result_array[2] == 'recursively'.chr(10)){
               return $shell_result_array[1];
          }else{
               return false;
          }
          */
     }
   
     function get_os() {
          $osname = php_uname();
          $osnameArray = explode(" ", $osname);
          return $osnameArray[0];
     }

     function ipfs_daemon() {
          $osname = $this->get_os();
          if ($osname == 'Windows') {
               //$command = 'start '.__DIR__.'\\..\\..'.enum::TOKENURI_PATH.'\\ipfs.exe daemon &';
               //exec($command);
               $command = 'start /B ' . __DIR__ . '\\..\\..' . enum::TOKENURI_PATH . '\\ipfs.exe daemon';
               pclose( popen( $command, 'r' ) );
               //exec(''.__DIR__.'\\..\\..'.enum::TOKENURI_PATH.'\\ipfs.exe daemon > NUL 2> NUL');
          }
          elseif($osname == 'Linux') {
               //$command = '..'.enum::TOKENURI_PATH.'/ipfs_linux daemon 2>>&1'; //리턴메시지볼떄
               //$command = '..'.enum::TOKENURI_PATH.'/ipfs_linux init';         //처음에 nginx 계정으로 init해야작동함. init하는 폴더에 nginx권한없을것임 /var/cache/nginx 를 nginx:nginx로변경해야함
               $command = '..' . enum::TOKENURI_PATH . '/ipfs_linux daemon 2>/dev/null >/dev/null &';
               $shell_result = shell_exec($command);
               //var_dump($shell_result);
          }
          elseif($osname == 'Darwin') {
               $command = '..' . enum::TOKENURI_PATH . '/ipfs daemon 2>/dev/null >/dev/null &';
               $shell_result = shell_exec($command);
          }
          
          return true;
     }

     function ipfs_isDaemon() {
          $osname = $this->get_os();
          if ($osname == 'Windows') {
               $command = 'tasklist | findstr ipfs';
               $shell_result = shell_exec($command);
               $shell_result_row = explode(chr(10), $shell_result);
               $cnt = 0;
               foreach ($shell_result_row as $val) {
                    $col = explode(" ", $val);
                    if ($col[0] == 'ipfs.exe') {
                         $cnt++;
                    }
               }
               
               if ($cnt > 0) {
                    return true;
               }
               else {
                    return false;
               }               
          }
          elseif ($osname == 'Linux') {
               //LINUX의 경우 nginx의 권한으로 ipfs init을 해줘야 오류가안나는데 sudo를 입력하면 root권한으로실행이된다.
               //그러므로  /var/cache/nginx 폴더의 오너를 nginx로 변경해주고 ipfs init을 먼저 한번 php를통해 날려준 후에야
               //작동이된다
               $command = '..' . enum::TOKENURI_PATH . '/ipfs_linux id 2>&1';
               $shell_result = shell_exec($command);
               $result = json_decode($shell_result, true);
               if ($result['Addresses'] == null) {
                    return false;
               }
               else {
                    return true;
               }
          }
          elseif ($osname == 'Darwin') {
               $command = '..' . enum::TOKENURI_PATH . '/ipfs id';
               $shell_result = shell_exec($command);
               $result = json_decode($shell_result, true);
               if ($result['Addresses'] == null) {
                    return false;
               }
               else {
                    return true;
               }               
          }
     }

     function ipfs_daemon_kill() {
          $osname = $this->get_os();
          if ($osname == 'Windows') {
               $command = 'taskkill -F -im ipfs.exe';
               shell_exec($command);
               return true;
          }
          elseif ($osname == 'Linux') {
               $command = '..' . enum::TOKENURI_PATH . '/ipfs_linux shutdown';
               $shell_result = shell_exec($command);
                return true;
          }
          elseif ($osname == 'Darwin') {
              $command = '..' . enum::TOKENURI_PATH . '/ipfs shutdown';
              $shell_result = shell_exec($command);
               return true;
          }
     }

     //소수점 8자리 문자열로 반환
     public function floattostr($val) {
          $val = sprintf("%0.8f", $val);
          preg_match("#^([\+\-]|)([0-9]*)(\.([0-9]*?)|)(0*)$#", trim($val), $o);
          return $o[1].sprintf('%d',$o[2]).($o[3]!='.'?$o[3]:'');
     }

     static public function getDirFiles($dir) {
          //__DIR__은 common파일이있는 src/Models/ 부터시작
          $scanDir = __DIR__ . '/../..' . $dir; 
          if (is_dir($scanDir)) {
               return scandir($scanDir);
          }
          else {
               return [];
          }
     }

     static public function ganarateNFTPNGTest($bg, $side, $pet, $star, $type) {
          switch ($type) {
               case 'thumbnail':
                    $destW = 282;
                    $destH = 282;
                    break;
               case 'main':
                    $destW = 536;
                    $destH = 536;
                    break;
               case 'origin':
                    $destW = 764;
                    $destH = 764;
                    break;                                             
          }
          //__DIR__은 common파일이있는 src/Models/ 부터시작
          $bgFile = __DIR__ . '/../..' . $bg; 
          $sideFile = __DIR__ . '/../..' . $side; 
          $petFile = __DIR__ . '/../..' . $pet; 
          $starFile = __DIR__ . '/../..' . $star; 

          //백그라운드 리사이징
          $bgLoaded = imagecreatefromjpeg($bgFile);
          list($bgW, $bgH) = getimagesize($bgFile);
          $ratioW = $destW / $bgW;
          $ratioH = $destH / $bgH;
          $resize_bgFile = imagecreatetruecolor($destW, $destH);
          imagecopyresampled($resize_bgFile, $bgLoaded, 0, 0, 0, 0, $destW, $destH, $bgW, $bgH); //resize

          //테두리 합성
          $sideLoaded = imagecreatefrompng($sideFile);
          list($sideW, $sideH) = getimagesize($sideFile);
          $sideDestW = (int)($sideW*$ratioW);
          $sideDestH = (int)($sideH*$ratioH);
          $resize_sideFile = imagecreatetruecolor($destW, $destH);
          imagecopyresampled($resize_bgFile, $sideLoaded, 0, 0, 0, 0, $sideDestW, $sideDestH, $sideW, $sideH); //resize

          //캐릭터 합성
          $petLodaed = imagecreatefrompng($petFile);
          list($petW, $petH) = getimagesize($petFile);
          //$petDestW = (int)($petW*$ratioW);
          //$petDestH = (int)($petH*$ratioH);
          $petDestW = (int)($petW*($ratioW * 1.7));
          $petDestH = (int)($petH*($ratioH * 1.7));
          $petPosW = ($destW / 2) - ($petDestW / 2);
          $petPosH = ($destH / 2) - ($petDestH / 2);
          //imagecopyresampled($resize_bgFile, $petLodaed, $petPosW, $petPosH, 0, 0, $petDestW, $petDestH, $petW, $petH);

          $starLodaed = imagecreatefrompng($starFile);
          list($starW, $starH) = getimagesize($starFile);
          $starDestW = (int)($starW*$ratioW);
          $starDestH = (int)($starH*$ratioH);
          $starPosW = ($destW * 0.88) - $starDestW;
          $starPosH = ($destW * 0.2) - $starDestH;
          for($grade = 0; $grade < 2; $grade++){
               $starOffsetH = $grade * ($starDestH + ($starDestH * 0.2));
               imagecopyresampled($resize_bgFile, $starLodaed, $starPosW, $starPosH+$starOffsetH, 0, 0, $starDestW, $starDestH, $starW, $starH); //resize
          }

          imagepng($resize_bgFile, __DIR__ . '/../../shell/' . $type . '.png');
          //header('Content-type: image/jpeg;');
          //imagepng($resize_bgFile);
          //exit;

     }     

     static public function ganarateNFTPNG($bgFile, $petFile) {
          try {
               foreach (enum::NFT_IMAGE_FILES as $key => $val) {
                    //BG파일 리사이징
                    $aryfilename = explode('.', $bgFile);
                    $ext = strtolower($aryfilename[count($aryfilename)-1]);
                    if ($ext == 'jpg' || $ext == 'jpeg') {
                         $bgLoaded = imagecreatefromjpeg($bgFile);
                    }
                    elseif ($ext == 'png') {
                         $bgLoaded = imagecreatefrompng($bgFile);
                    }
                    
                    list($bgW,$bgH) = getimagesize($bgFile);
                    $ratioW = $val['sizeW'] / $bgW;
                    $ratioH = $val['sizeW'] / $bgH;
                    $resize_bgFile = imagecreatetruecolor($val['sizeW'], $val['sizeH']);
                    imagecopyresampled($resize_bgFile, $bgLoaded, 0, 0, 0, 0, $val['sizeW'], $val['sizeH'], $bgW, $bgH); //resize

                    //PET합성
                    $petLodaed = imagecreatefrompng($petFile);
                    list($petW,$petH) = getimagesize($petFile);
                    $petDestW = (int)($petW*($ratioW)); //펫 크기가 좀 작게들어온거같아서 1.7배율을 해준건데 업로드이미지 보고 조절하자 (크기는 고정으로 넣어야한다고 전달하자)
                    $petDestH = (int)($petH*($ratioH));
                    $petPosW = ($val['sizeW'] / 2) - ($petDestW / 2);
                    $petPosH = ($val['sizeH'] / 2) - ($petDestH / 2);
                    imagecopyresampled($resize_bgFile, $petLodaed, $petPosW, $petPosH, 0, 0, $petDestW, $petDestH, $petW, $petH);

                    //파일저장
                    if (imagepng($resize_bgFile, __DIR__ . '/../..' . $val['savePath'] . '/' . $val['filename']) == false) {
                         return false;
                    }
               }
               return true;
          }
          catch (Exception $e) {
               return false;
          }
     }
     
     static public function ganarateNFTImage($imageFile) {
          try {
               foreach (enum::NFT_IMAGE_FILES as $key => $val) {
                    //BG파일 리사이징
                    $aryfilename = explode('.', $imageFile->getClientFilename());
                    $ext = strtolower($aryfilename[count($aryfilename)-1]);
                    if ($ext == 'jpg' || $ext == 'jpeg') {
                         $imageLoaded = imagecreatefromjpeg($imageFile->file);
                    }
                    elseif ($ext == 'png') {
                         $imageLoaded = imagecreatefrompng($imageFile->file);
                    }
                    
                    list($bgW,$bgH) = getimagesize($imageFile->file);
                    $ratioW = $val['sizeW'] / $bgW;
                    $ratioH = $val['sizeW'] / $bgH;
                    $resize_imageFile = imagecreatetruecolor($val['sizeW'], $val['sizeH']);
                    imagecopyresampled($resize_imageFile, $imageLoaded, 0, 0, 0, 0, $val['sizeW'], $val['sizeH'], $bgW, $bgH); //resize

                    //파일저장
                    if (imagepng($resize_imageFile, __DIR__ . '/../..' . $val['savePath'] . '/' . $val['filename']) == false) {
                         return false;
                    }
               }
               return true;
          }
          catch(Exception $e) {
               return false;
          }
     }          

     static function image_resize($file_name, $width, $height, $crop=FALSE) {
          list($wid, $ht) = getimagesize($file_name);
          $r = $wid / $ht;
          if ($crop) {
               if ($wid > $ht) {
                    $wid = ceil($wid - ($width * abs($r - $width / $height)));
               }
               else {
                    $ht = ceil($ht - ($ht * abs($r - $width / $height)));
               }
               $new_width = $width;
               $new_height = $height;
          }
          else {
               if ($width/$height > $r) {
                    $new_width = $height * $r;
                    $new_height = $height;
               }
               else {
                    $new_height = $width / $r;
                    $new_width = $width;
               }
          }
          $aryfilename = explode('.', $file_name);
          $ext = $aryfilename[count($aryfilename) - 1];
          switch ($ext) {
               case 'png':
                    $source = imagecreatefrompng($file_name);
                    break;
               case 'jpg':
               case 'jpeg':
                    $source = imagecreatefromjpeg($file_name);
                    break;
               case 'bmp':
                    $source = imagecreatefrombmp($file_name);
                    break;
               case 'gif':
                    $source = imagecreatefromgif($file_name);
                    break;                                                  
               default :
                    return false;
                    break;
          }
          
          $dst = imagecreatetruecolor($new_width, $new_height);
          imagecopyresampled($dst, $source, 0, 0, 0, 0, $new_width, $new_height, $wid, $ht);
          return $dst;
     }
       
     static public function getUserList() {
          //유저는 배포를 타고 배포된다. 퍼미션은 환경마다 별도로 가야한다. ignore처리
          $userFile = __DIR__ . '/Authority/user.json';
          if (file_exists($userFile)) {
               $fileSize = filesize($userFile) === 0 ? 1024 : filesize($userFile);
               $fp = fopen($userFile, "r") or die("Unable to open file!");
               $dataJson = fread($fp, $fileSize);
               $data = json_decode($dataJson, true);
               fclose($fp);
          }
          if (!isset($data)) {
               $data = [];
          }
          return $data;
     }

     static public function getUser($OperatorUID) {
          $userFile = __DIR__ . '/Authority/user.json';
          if (file_exists($userFile)) {
               $fileSize = filesize($userFile)===0?1024:filesize($userFile);
               $fp = fopen($userFile, "r") or die("Unable to open file!");
               $dataJson = fread($fp, $fileSize);
               $data = json_decode($dataJson, true);
               fclose($fp);
          }
          if (!isset($data)) {
               $data = [];
          }
          return $data[$OperatorUID] ?? false;
     }

     static public function InsertUser($params) {
          $userFile = __DIR__ . '/Authority/user.json';
          $result = false;
          $data = [];
          if (file_exists($userFile)) {
               $fp = fopen($userFile, "r") or die("Unable to open file!");
               $dataJson = '';
               while (!feof($fp)) {  //This looped forever
                    $dataJson .= fread($fp, 1024);
               }               
               $data = json_decode($dataJson, true);
               fclose($fp);
          }

          $timestamp = strtotime("+9 hours");
          $LoginDate = date('Y-m-d H:i:s', $timestamp);
          $CreatedDate = date('Y-m-d H:i:s', $timestamp);
          
          if (!isset($params['OperatorUID'])) {
              return false; 
          }

          $data[$params['OperatorUID']] = array(
               'OperatorUID' => $params['OperatorUID'],
               'Password' => $params['Password'],
               'OperatorName' => $params['OperatorName'],
               'CompanyName' => $params['CompanyName'],
               'LoginDate' => $LoginDate,
               'CreatedDate' => $CreatedDate
          );
          $dataJson = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
          $genFile = fopen($userFile, "w") or die("Unable to open file!");
          fwrite($genFile, $dataJson);
          fclose($genFile);

          if (file_exists($userFile)) {
               $result = true;
          }
          return $result;
     }

     static public function UpdateUser($params) {
          $userFile = __DIR__ . '/Authority/user.json';
          $result = false;
          $data = [];
          if (file_exists($userFile)) {
               $fp = fopen($userFile, "r") or die("Unable to open file!");
               $dataJson = '';
               while (!feof($fp)) {  //This looped forever
                    $dataJson .= fread($fp, 1024);
               }               
               $data = json_decode($dataJson, true);
               fclose($fp);
          }

          if (!isset($params['OperatorUID'])) {
              return false; 
          }

          $data[$params['OperatorUID']] = array(
               'OperatorUID' => $params['OperatorUID'],
               'Password' => $params['Password'],
               'OperatorName' => $params['OperatorName'],
               'CompanyName' => $params['CompanyName'],
               'LoginDate' => $data[$params['OperatorUID']]['LoginDate'],
               'CreatedDate' => $data[$params['OperatorUID']]['CreatedDate']
          );
          $dataJson = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
          $genFile = fopen($userFile, "w") or die("Unable to open file!");
          fwrite($genFile, $dataJson);
          fclose($genFile);

          if (file_exists($userFile)) {
               $result = true;
          }
          return $result;
     }

     static public function DeleteUser($OperatorUID) {
          $userFile = __DIR__ . '/Authority/user.json';
          $result = false;
          $data = [];
          if (file_exists($userFile)) {
               $fp = fopen($userFile, "r") or die("Unable to open file!");
               $dataJson = '';
               while (!feof($fp)) {  //This looped forever
                    $dataJson .= fread($fp, 1024);
               }               
               $data = json_decode($dataJson, true);
               fclose($fp);
          }
          
          if (!isset($OperatorUID)) {
              return false; 
          }

          $keyToRemove = array_search($data[$OperatorUID], $data);
          if ($keyToRemove !== false) {
               unset($data[$keyToRemove]);
          }

          $dataJson = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
          $genFile = fopen($userFile, "w") or die("Unable to open file!");
          fwrite($genFile, $dataJson);
          fclose($genFile);

          if (file_exists($userFile)) {
               $result = true;
          }
          return $result;
     }

     static public function getUserPermission($OperatorUID) {
          $serverName = $_SESSION['ServerType'] ?? '';
          $result = false;
          if ($serverName != '') {
               $userFile = __DIR__ . '/Authority/permission_' . $serverName . '.json';
               $result = false;
               $data = [];
               if (file_exists($userFile)) {
                    $fileSize = filesize($userFile) === 0 ? 1024 : filesize($userFile);
                    $fp = fopen($userFile, "r") or die("Unable to open file!");
                    $dataJson = fread($fp, $fileSize); 
                    $data = json_decode($dataJson, true);
                    fclose($fp);
               }
               else {
                    //파일이 없으면 생성
                    $genFile = fopen($userFile, "w") or die("Unable to open file!");
                    fwrite($genFile, '[]');
                    fclose($genFile);
               }
               if (file_exists($userFile)) {
                    $result = $data[$OperatorUID] ?? [];
               }
          }
          return $result;
     }

     static public function UpdateUserPermission($OperatorUID, $MenuID, $Authority) {
          $serverName = $_SESSION['ServerType'];
          $userFile = __DIR__ . '/Authority/permission_' . $serverName . '.json';
          $result = false;
          $data = [];
          if (file_exists($userFile)) {
               $fp = fopen($userFile, "r") or die("Unable to open file!");
               $dataJson = '';
               while (!feof($fp)) {  //This looped forever
                    $dataJson .= fread($fp, 1024);
               }               
               $data = json_decode($dataJson, true);
               fclose($fp);
          }

          $data[$OperatorUID][$MenuID] = array(
               'MenuID' => $MenuID,
               'Authority' => $Authority
          );
          $dataJson = json_encode($data);
          $genFile = fopen($userFile, "w") or die("Unable to open file!");
          fwrite($genFile, $dataJson);
          fclose($genFile);

          if (file_exists($userFile)) {
               $result = true;
          }
          return $result;
     }     

     public function getAccountInfo($ID, $PASS) {
          $user = $this->getUser($ID);
          if (!is_array($user)) {
               return array('Code' => -1);
          }
          else {
               if ($user['Password'] != $PASS) {
                    return array('Code' => -2);
               }
               else {
                    $data['Code'] = 1;
                    $data['Data'] = array(
                         'id' => $ID,
                         'company' => $user['CompanyName'],
                         'displayname' => $user['OperatorName'],
                         'title' => $user['CompanyName'],
                         'department' => $user['CompanyName'],
                    );
                    return $data;
               }
          }
     }

     // 단일 시트 엑셀
     static function getSpreadsheet($data) {
          //엑셀 만들어서 다운로드...
          $spreadsheet = new Spreadsheet();
          $sheet = $spreadsheet->getActiveSheet();

          $char = 'A';
          $sellno = 1;
          foreach ($data['Data'] as $key => $value) {
               //본문
               $subChar = 'A';
               foreach ($value as $key2 => $value2) {
                    //$subChar++;
                    if (1 == $sellno) {
                         $titleNo = $subChar . $sellno;
                         $sheet->setCellValue($titleNo, $key2);
                    }

                    $dataNo = $subChar . ($sellno+1);
                    // 운영 > PLATFORM > SUI 출금 메뉴에서 엑셀 다운로드 할 때 특정 열 텍스트 형식으로 고정
                    if ($data['Title'] == 'SuiWithdraw') {
                         // D, E, H열
                         if ($subChar == 'D' || $subChar == 'E' || $subChar == 'H') {
                              $sheet->setCellValueExplicit($dataNo, $value2, DataType::TYPE_STRING);
                         }
                         else {
                              $sheet->setCellValue($dataNo, $value2);
                         }
                    }
                    // 운영 > PLATFROM > 사전 판매 > 상품 구매 내역에서 엑셀 다운로드 할 때 특정 열 텍스트 형식으로 고정
                    else if ($data['Title'] == 'PreSalePurchaseLog') {
                         // A, B, F, K열
                         if ($subChar == 'A' || $subChar == 'B' || $subChar == 'F' || $subChar == 'K') {
                              $sheet->setCellValueExplicit($dataNo, $value2, DataType::TYPE_STRING);
                         }
                         else {
                              $sheet->setCellValue($dataNo, $value2);
                         }
                    }
                    // 나머지
                    else {
                         $sheet->setCellValue($dataNo, $value2);
                    }

                    $subChar++;
               }

               //날짜
               $sellno++;
          }

          $highestColumn = $sheet->getHighestColumn();
          $highestRow = $sheet->getHighestRow();
          
          // 테이블 테두리
          $borderStyle = [
               'borders' => [
                    'allBorders' => [
                    'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
                    ]
               ]
          ];

          // 테이블 헤더 스타일
          $sheet->getStyle("A1:{$highestColumn}1")->applyFromArray([
               'fill' => [
                    'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                    'color' => ['rgb' => 'A6A6A6'], // 회색
               ],
               'alignment' => [
                    'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                    'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
               ],
               'font' => [
                    'bold' => true,
               ],
          ]);

          // 스타일 적용
          $sheet->getStyle("A1:{$highestColumn}{$highestRow}")->applyFromArray($borderStyle);

          // 열 너비 자동 조정
          foreach ($spreadsheet->getAllSheets() as $sheet) {
               foreach ($sheet->getColumnIterator() as $column) {
                    $sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
               }
          }
          
          // 시트 열었을 때 커서 위치 지정
          $sheet->setSelectedCell('A1');

          $writer = new Xlsx($spreadsheet);

          if ($data['StartDate'] != "" && $data['EndDate'] != "") {
               $title = $data['Title'] . "(" . $data['StartDate'] . "~" . $data['EndDate'] . ")";
          }
          else {
               $title = $data['Title'];
          }

          $fileName = $title . ".xlsx";
          header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
          header('Content-Disposition: attachment; filename="' . urlencode($fileName) . '"');
          ob_start();
          $writer->save('php://output');
          $xlsData = ob_get_contents();
          ob_end_clean();

          $result = array();
          $result['op'] = "ok";
          $result['name'] = $fileName;
          $result['file'] = "data:application/vnd.ms-excel;base64," . base64_encode($xlsData);

          // $result['TEST'] = $data;

          return $result;
     }

     // 멀티 시트 엑셀 데이터 가공
     static function buildExcelData($title, $startDate, $endDate, $list, $columns) {
          $filteredList = [];

          foreach ($list as $item) {
               $row = [];
               foreach ($columns as $col) {
                    $row[$col] = $item[$col] ?? '';
               }
               $filteredList[] = $row;
          }

          return [
               'Title' => $title,
               'StartDate' => $startDate,
               'EndDate' => $endDate,
               'Data' => $filteredList
          ];
     }

     // 멀티 시트 엑셀
     static public function getSpreadsheetMulti($data) {
          $spreadsheet = new Spreadsheet();

          $first = true;
          foreach ($data['Sheets'] as $sheetInfo) {

               // 시트 생성
               if ($first) {
                    $sheet = $spreadsheet->getActiveSheet();
                    $sheet->setTitle($sheetInfo['SheetName']);
                    $first = false;
               }
               else {
                    $sheet = $spreadsheet->createSheet();
                    $sheet->setTitle($sheetInfo['SheetName']);
               }

               $rows = $sheetInfo['Data'];

               $sellno = 1;
               foreach ($rows as $value) {

                    $subChar = 'A';
                    foreach ($value as $key2 => $value2) {

                         // 첫 번째 row는 컬럼 이름
                         if ($sellno == 1) {
                              $titleNo = $subChar . $sellno;
                              $sheet->setCellValue($titleNo, $key2);
                         }

                         $dataNo = $subChar . ($sellno + 1);

                         // 운영 > PLATFORM > 사전 판매 > 상품 구매 내역에서 특정 열 텍스트로 고정
                         if ($data['Title'] == 'PreSalePurchaseLog') {
                              // A, B, F, K열 고정
                              if ($subChar == 'A' || $subChar == 'B' || $subChar == 'F' || $subChar == 'K') {
                                   $sheet->setCellValueExplicit($dataNo, $value2, DataType::TYPE_STRING);
                              }
                              else {
                                   $sheet->setCellValue($dataNo, $value2);
                              }
                         }
                         else {
                              // 기본
                              $sheet->setCellValue($dataNo, $value2);
                         }

                         $subChar++;
                    }

                    $sellno++;
               }

               if ($data['Title'] == 'PreSalePurchaseLog') {
                    $totalRow = $sellno + 1; // 데이터 끝난 다음 다음 줄
                    $startCol = 'A';
                    $endCol = 'M'; // Merge A~M
                    $sumCol = 'N'; // 합계 표시 컬럼

                    // 합계 계산
                    $sum = 0;
                    foreach ($rows as $r) {
                         if (isset($r['AdjQuantityStr'])) {
                              // $sum += floatval($r['AdjQuantityStr']);
                              
                              // 콤마 제거 후 숫자 변환
                              $value = str_replace(',', '', $r['AdjQuantityStr']);
                              $sum += (float)$value;
                         }
                    }

                    // A ~ M 병합
                    $sheet->mergeCells("{$startCol}{$totalRow}:{$endCol}{$totalRow}");
                    $sheet->setCellValue("{$startCol}{$totalRow}", "총 코인 소모 수량");

                    // 합계 값
                    // 3자리마다 콤마
                    $formattedSum = self::formatNumberSmart($sum);
                    $sheet->setCellValue("{$sumCol}{$totalRow}", $formattedSum);

                    // 테이블 테두리
                    $borderStyle = [
                         'borders' => [
                              'allBorders' => [
                              'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
                              ]
                         ]
                    ];

                    // 병합된 셀(A~M)의 색상, 가운데 정렬
                    $sheet->getStyle("{$startCol}{$totalRow}:{$endCol}{$totalRow}")->applyFromArray([
                         'fill' => [
                              'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                              'color' => ['rgb' => 'FFFF00']
                         ],
                         'alignment' => [
                              'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                              'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER
                         ]
                    ]);

                    $highestColumn = $sheet->getHighestColumn();
                    $highestRow = $sheet->getHighestRow();

                    // 테이블 헤더 스타일
                    $sheet->getStyle("A1:{$highestColumn}1")->applyFromArray([
                         'fill' => [
                              'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                              'color' => ['rgb' => 'A6A6A6'], // 회색
                         ],
                         'alignment' => [
                              'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                              'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
                         ],
                         'font' => [
                              'bold' => true,
                         ],
                    ]);

                    // 스타일 적용
                    $sheet->getStyle("A1:{$highestColumn}{$highestRow}")->applyFromArray($borderStyle);

                    // 시트 열었을 때 커서 위치 지정
                    $sheet->setSelectedCell('A1');
               }
          }

          // 열 너비 자동 조정
          foreach ($spreadsheet->getAllSheets() as $sheet) {
               foreach ($sheet->getColumnIterator() as $column) {
                    $sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
               }
          }

          // 파일명 구성
          if (!empty($data['StartDate']) && !empty($data['EndDate'])) {
               $title = $data['Title'] . "(" . $data['StartDate'] . "~" . $data['EndDate'] . ")";
          }
          else {
               $title = $data['Title'];
          }

          $fileName = $title . ".xlsx";

          // 파일 열때 첫번째 시트 활성화
          $spreadsheet->setActiveSheetIndex(0);

          // 다운로드
          $writer = new Xlsx($spreadsheet);
          header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
          header('Content-Disposition: attachment; filename="' . urlencode($fileName) . '"');

          ob_start();
          $writer->save('php://output');
          $xlsData = ob_get_contents();
          ob_end_clean();

          return [
               'op' => 'ok',
               'name' => $fileName,
               'file' => "data:application/vnd.ms-excel;base64," . base64_encode($xlsData)
          ];
     }

     // 3자리마다 콤마 표기(정수, 실수 구분)
     static public function formatNumberSmart($value) {
          // 숫자가 아니면 그대로 반환
          if (!is_numeric($value)) {
               return $value;
          }

          // 정수인지 판별
          if ((int)$value == $value) {
               return number_format($value);
          }

          // 실수면 소수점 자리 계산
          $decimalLength = 0;

          if (strpos($value, '.') !== false) {
               $decimalLength = strlen(substr(strrchr($value, '.'), 1));
          }

          // 소수점 자리수를 유지하며 콤마 추가
          return number_format($value, $decimalLength);
     }

     function setLog(&$resData, $action, $input, $output, $resultCode) {
          $result = array();

          $input['Path'] = $resData['Path'];

          $result['eventType'] = $action;
          $result['resultCode'] = $resultCode;     
          $result['input'] = $input;    
          $result['output'] = $output;

          return $result;
     }

     function setApiCallLog(&$resData, $action, $server, $portType, $apiUrl, $input, $output, $resultCode) {
          $result = array();

          $input['Path'] = $resData['Path'];

          $result['eventType'] = $action;
          $result['resultCode'] = $resultCode;
          $result['server'] = $server;
          $result['portType'] = $portType;
          $result['api'] = $apiUrl;
          $result['input'] = $input;    
          $result['output'] = $output;

          return $result;
     }

     function getDashMeta($container) {
          $marketServer = $container['dashserver'];
          $url = $marketServer['ex'] . '/db/meta';

          $return = $this->httpcall('get', $url, []);
          return $return['value'] ?? [];
     }

     public function getNftPack($container, $pack_id) {
          $marketServer = $container['marketserver'];
          $url = $marketServer['in'] . '/nft/pack';
          $params['pack_id'] = $pack_id;

          $return = $this->httpcall('get', $url, $params);
          return $return['value'] ?? [];
     }

     // 이 함수 사용하던거 전부 주석 처리
     public function getCoinsMeta($container) {
          $marketServer = $container['marketserver'];
          $url = $marketServer['in'] . '/meta/coins';

          $return = $this->httpcall('get', $url, []);
          return $return['value'] ?? [];
     }

     public function getBrandsMeta($container) {
          $marketServer = $container['marketserver'];
          $url = $marketServer['in'] . '/meta/brands';

          $return = $this->httpcall('get', $url, []);
          return $return['value'] ?? [];
     }

     public function getCategoriesMeta($container) {
          $marketServer = $container['marketserver'];
          $url = $marketServer['in'] . '/meta/categories';

          $return = $this->httpcall('get', $url, []);
          return $return['value'] ?? [];
     }
     
     public function getNftPackList($container, $page, $pageSize) {
          $marketServer = $container['marketserver'];
          $url = $marketServer['in'] . '/nft/pack/list';
          $params['page_offset'] = $page;
          $params['page_size'] = $pageSize;

          $return = $this->httpcall('get', $url, $params);
          return $return['value'] ?? [];
     }

     public function getApi($container, $server, $portType, $url, $params) {
          $targetServer = $container->$server;
          $targetUrl = $targetServer[$portType] . $url;
          
          if (isset($params)) {
               $return = $this->httpcall('get', $targetUrl, $params);
          }
          else {
               $return = $this->httpcall('get', $targetUrl, []);
          }
          
          return $return ?? [];
     }

     public function postApi($container, $server, $portType, $url, $refresh_target, $params) {
          $targetServer = $container->$server;    
          $targetUrl = $targetServer[$portType] . $url;
          
          if (isset($refresh_target)) {
               $return = $this->httpcall('post', $targetUrl, ['refresh' => true, 'refresh_target' => $refresh_target]);
          }
          
          if (isset($params)) {
               $return = $this->httpcall('post', $targetUrl, $params);
          }

          if (!isset($refresh_target) && !isset($params)) {
               $return = $this->httpcall('post', $targetUrl, []);
          }
          
          return $return??[];
     }

     public function putApi($container, $server, $portType, $url, $params) {
          $targetServer = $container->$server;
          $targetUrl = $targetServer[$portType] . $url;
          
          $return = $this->httpcall('put', $targetUrl, $params);
          
          return $return??[];
     }

     public function deleteApi($container, $server, $portType, $url, $params) {
          $targetServer = $container->$server;
          $targetUrl = $targetServer[$portType] . $url;
          
          $return = $this->httpcall('delete', $targetUrl, $params);
          
          return $return??[];
     }

     public function generate_tokenuri($pack_name, $desc, $image, $animation, $pack_id, $add_attributes) {
          $token['description'] = $desc;
          $token['external_url'] = 'https://inno.lumiwavelab.com/';
          $token['image'] = $image;
          $token['name'] = $pack_name;
          $token['animation_url'] = $animation;
          $attributes = array();
          if (count($add_attributes) > 0) {
               foreach ($add_attributes as $key => $val) {
                    $attributes[] = $val;
               }
          }
          $token['attributes'] = $attributes;
          return json_encode($token, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
     }
     
     public function NFTPackUpdate($container, $params) {
          $marketServer = $container['marketserver'];
          $url = $marketServer['in'] . '/nft/pack';

          return $this->httpcall('put', $url, $params);
     }
     
     public function getServerName($container) {
          $port = $_SERVER["SERVER_PORT"];
          
          $ports = $container->get('settings')['port'];
          if (isset($ports)) {
               foreach ($ports as $key => $value) {
                    if ((int)$value == $port) {
                         $serverType = $key;
                    }
               }
          }

          return $serverType;
     }

     // 실수형 데이터 가져올때 정수가 0이면 0 표기 안될때 사용
     public function getFloatFormat($value) {
          $arrayValue = explode('.', $value);
          
          if (isset($arrayValue[1])) {
               if ($arrayValue[0] === '') {
                    $result = '0.' . $arrayValue[1];
               }
               else {
                    $arrayValueInt = (int)$arrayValue[0];
                    $result = $arrayValueInt . '.' . $arrayValue[1];
               }
          }
          else {
               $result = $value;
          }

          return $result;
     }

     // 실수형 데이터 가져올때 정수가 0이면 0 표기 안될때 사용 (정수에 3자리마다 콤마)
     public function getFloatCommaFormat($value) {
          $arrayValue = explode('.', $value);
          if (isset($arrayValue[1])) {
               if ($arrayValue[0] === '') {
                    $result = '0.' . $arrayValue[1];
               }
               else {
                    $arrayValueInt = number_format($arrayValue[0]);
                    $result = $arrayValueInt . '.' . $arrayValue[1];
               }
          }
          else {
               $result = $value;
          }

          return $result;
     }


     ////////////////////// 메타데이터 //////////////////////
     // 고객사 목록 - 전체 컬럼
     public function getCompanies($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);
          
          $data = $AccountDB->USPT_Scan_Companies();
          
          if ($data['Code'] == 1) {
               $result = $data['Data']['List'];
          }
          
          return $result;
     }
     
     // 고객사 목록 - CompanyID, CompanyName만
     public function getCompanyInfo($container) {
          $result = array();
          $data = $this->getCompanies($container);
          if ($data) {
               foreach ($data as $key => $value) {
                    $result[(int)$value['CompanyID']] = $value['CompanyName'];
               }
          }

          return $result;
     }

     // 코인 계열 목록 - 전체 컬럼
     public function getBaseCoins($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);
          
          $data = $AccountDB->USPT_Scan_BaseCoins();
          
          if ($data['Code'] == 1) {
               foreach ($data['Data']['List'] as $key => $value) {
                    $result[(int)$value['BaseCoinID']] = $value;
               }
          }
          
          return $result;
     }

     // 코인 계열 목록 - BaseCoinID, BaseCoinName만
     public function getBaseCoinInfo($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);
          
          $data = $AccountDB->USPT_Scan_BaseCoins();
          if ($data['Code'] == 1) {
               foreach ($data['Data']['List'] as $key => $value) {
                    $result[(int)$value['BaseCoinID']] = $value['BaseCoinName'];
               }
          }

          return $result;
     }

     // 앱 목록 - 전체 컬럼
     public function getApplications($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);

          $data = $AccountDB->USPT_Scan_Applications();
          if ($data['Code'] == 1) {
               $result = $data['Data']['List'];
          }
          
          return $result;
     }

     // 앱 목록 - AppID, AppName만
     public function getApplicationsInfo($container) {
          $result = array();
          $data = $this->getApplications($container);
          if ($data) {
               foreach ($data as $key => $value) {
                    $result[(int)$value['AppID']] = $value['AppName'];
               }
          }

          return $result;
     }

     // 코인 목록 - 전체 컬럼
     public function getCoins($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);

          $data = $AccountDB->USPT_Scan_Coins();
          if ($data['Code'] == 1) {
               foreach ($data['Data']['List'] as $key => $value) {
                    $result[(int)$value['CoinID']] = $value;
               }
          }

          return $result;
     }

     // 코인 목록 - CoinID, CoinName만
     public function getCoinsName($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);

          $data = $AccountDB->USPT_Scan_Coins();
          if ($data['Code'] == 1) {
               foreach ($data['Data']['List'] as $key => $value) {
                    $result[(int)$value['CoinID']] = $value['CoinName'];
               }
          }

          return $result;
     }

     // 코인 목록 - CoinID, CoinSymbol만
     public function getCoinsWithCoinSymbol($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);

          $data = $AccountDB->USPT_Scan_Coins();
          if ($data['Code'] == 1) {
               foreach ($data['Data']['List'] as $key => $value) {
                    $result[(int)$value['CoinID']] = $value['CoinSymbol'];
               }
          }

          return $result;
     }

     // 포인트 목록 - 전체 컬럼
     public function getPoints($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);

          $data = $AccountDB->USPT_Scan_Points();
          if ($data['Code'] == 1) {
               $result = $data['Data']['List'];
          }

          return $result;
     }

     // 포인트 목록 - PointID, PointName만
     public function getPointsInfo($container) {
          $result = array();
          $data = $this->getPoints($container);
          if ($data) {
               foreach ($data as $key => $value) {
                    $result[(int)$value['PointID']] = $value['PointName'];
               }
          }

          return $result;
     }

     // 지갑 플랫폼 목록 - WalletTypeID, WalletTypeName만
     public function getWalletInfo($container) {
          $result = array();
          $AccountDB = new AccountDB($container, true);

          $data = $AccountDB->USPT_Scan_WalletTypes();
          if ($data['Code'] == 1) {
               foreach ($data['Data']['List'] as $key => $value) {
                    $result[(int)$value['WalletTypeID']] = $value['WalletTypeName'];
               }
          }

          return $result;
     }
     ////////////////////// 메타데이터 //////////////////////

}
