<?php

namespace Hura8\System;

use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

class UploadZip
{
    protected $upload_folder;

    protected $allow_file_extensions = array(
        ".jpeg", ".jpg", ".gif", ".png", ".webp", ".ico",
        ".html", ".htm",
        ".js",
        ".css",
    );


    public function __construct($upload_folder) {
        $this->upload_folder = PUBLIC_DIR . "/" . $upload_folder;
    }


    public function getFileList() {
        $file_list = [];
        $this->scanFileInDir( $this->upload_folder, $file_list);

        return $file_list;
    }


    protected function scanFileInDir($folder, &$file_list = []) {
        $dir = opendir($folder);
        while(( $file = readdir($dir)) ) {
            if (( $file != '.' ) && ( $file != '..' )) {
                if ( is_dir($folder. '/' . $file) ) {
                    $this->scanFileInDir($folder. '/' . $file, $file_list);
                }
                else {
                    $file_list[] = str_replace(PUBLIC_DIR . "/", "", $folder .'/'. $file);
                }
            }
        }
        closedir($dir);
    }


    public function handleUpload($input_file_name='file') {

        if(!$this->check_upload_folder()) {
            return [
                'status' => 'error',
                'message' => "Target folder not exist or writeable. Folder: ". $this->upload_folder,
            ];
        }

        $filename   = $_FILES[$input_file_name]["name"];
        $source     = $_FILES[$input_file_name]["tmp_name"];
        $type       = $_FILES[$input_file_name]["type"];

        list($filename_no_ext, $file_ext) = explode(".", $filename);
        $filename_no_ext = preg_replace("/[^a-z0-9_]/i", "", $filename_no_ext);

        if(!strtolower($file_ext) == 'zip') {
            return [
                'status' => 'error',
                'message' => "File này không phải file .zip, vui lòng sửa và upload lại",
            ];
        }

        //unzip to a temporary folder, test the content if ok then move to desired folder
        $target_path_tmp = $this->uploadToTmpFolder($source, $filename);
        $this->removeDangerousFiles($target_path_tmp);
        $this->transferFileFromTmpFolder($target_path_tmp);

        return [
            'status' => 'ok',
            'message' => "",
        ];
    }


    protected function uploadToTmpFolder($source, $filename ) {
        $target_path_tmp = $this->upload_folder . "/tmp_".CURRENT_TIME;  // change this to the correct site path
        if(!file_exists($target_path_tmp)) @mkdir($target_path_tmp, 0755);

        //$target_path = $this->upload_folder . "/".$filename_no_ext;
        //if(!file_exists($target_path)) mkdir($target_path, 0755);

        if(move_uploaded_file($source, $target_path_tmp . "/".$filename)) {
            $zip = new \ZipArchive();
            $x = $zip->open($target_path_tmp . "/".$filename);
            if ($x === true) {
                $zip->extractTo($target_path_tmp); // change this to the correct site path
                $zip->close();
            }
            @unlink($target_path_tmp . "/".$filename);
        }

        return $target_path_tmp;
    }


    protected function removeDangerousFiles($target_path_tmp) {
        foreach ( new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($target_path_tmp),
            RecursiveIteratorIterator::SELF_FIRST) as $item
        ) {
            if(!$item->isDir()) {
                //only allow : image, html file
                $ext = strtolower(strrchr($item, "."));
                if(in_array($ext, $this->allow_file_extensions )){
                    //copy to new folder
                    $list_valid_file[] = (string) $item;

                    if(strpos($item, ".php") !== false) {
                        //remove potetial harmful files like: r57.php.jpg, c100.php.html
                        @unlink($item);
                        break;
                    }
                }else{
                    @unlink($item);
                    break;
                }
            }
        }
    }


    protected function transferFileFromTmpFolder($target_path_tmp) {
        recursive_copy($target_path_tmp, $this->upload_folder);
        removeDir($target_path_tmp);
    }

    protected function check_upload_folder() {
        if(!file_exists($this->upload_folder)) {
            @mkdir($this->upload_folder, 0755, true);
        }

        return (file_exists($this->upload_folder) && is_writable($this->upload_folder)) ;
    }


    public function get_upload_size_limit() {
        $max_upload = (int)(ini_get('upload_max_filesize'));
        $max_post = (int)(ini_get('post_max_size'));
        $memory_limit = (int)(ini_get('memory_limit'));
        return min($max_upload, $max_post, $memory_limit);
    }

}
