<?php

use Aws\Exception\AwsException;
use Aws\S3\S3Client;

/**
 * 
 * @author Anthony
 *
 */
class AWSMangos3Bucket {
    
    /**
     * 
     * @var string
     */
    private const BUCKET_NAME = "iwl-world-stg";
    
    /**
     * 
     * @var AWSMangos3Bucket
     */
    private static $instance = null;
    
    /**
     * 
     * @var S3Client
     */
    private $s3;
    
    private function __construct(){
        $this->s3 = new S3Client([
            "version" => "latest",
            'region'  => 'ap-southeast-1',
            'credentials' => [
                'key'    => 'AKIARMKWQUBIX45B6GR7',
                'secret' => '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',
            ]
        ]);
    }
    
    /**
     * 
     * syncing a file to bucket
     * 
     * @param string $filekey
     * @param string $sourceFilePath
     * @return boolean
     */
    public function uploadFile(string $filekey, string $sourceFilePath){
        try{
            // Upload the file to S3
            $this->s3->putObject([
                'Bucket' => self::BUCKET_NAME,
                'Key'    => $filekey,
                'SourceFile' => $sourceFilePath,
            ]);
            
            // Print the URL of the uploaded file
            return true;
        }catch(AwsException $ex){
            return false;
        }
    }
    
    /**
     * 
     * unlinks a file from bucket
     * 
     * @param string $filekey
     * @return boolean
     */
    public function deleteFile(string $filekey){
        try {
            // Delete the object
            $result = $this->s3->deleteObject([
                'Bucket' => self::BUCKET_NAME,
                'Key'    => $filekey,
            ]);
            
            // Check if the deletion was successful
            return $result ? true : false;
        } catch (AwsException $ex) {
            return false;
        }
    }
    
    /**
     * 
     * syncing the directory to bucket
     * 
     * @param string $directoryPath
     */
    public function uploadDirectory(string $directoryPath, string $keyPrefix = null){
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directoryPath));
        
        foreach($files as $file){
            if($file->isFile()){
                $filekey = str_replace("\\", "/",
                    substr($file->getPathname(), strrpos($directoryPath, basename($directoryPath))));
                
                if(!is_null($keyPrefix)){
                    $filekey = "{$keyPrefix}/{$filekey}";
                }
                
                $this->uploadFile($filekey, $file->getPathname());
            }
        }
    }
    
    /**
     * 
     * used as a tool to remove the designated local directory from local storage 
     * after syncing to s3 bucket
     * 
     * @param string $directoryPath
     * @return boolean
     */
    public function deleteLocalDirectory(string $directoryPath){
        if(!is_dir($directoryPath)) {
            return false; // Not a directory
        }
        
        $items = array_diff(scandir($directoryPath), array('.', '..')); // Get all items in the directory
        
        foreach ($items as $item) {
            $path = "{$directoryPath}/{$item}";
            
            if(is_dir($path)) {
                $this->deleteDirectory($path); // Recursively delete subdirectories
            }else{
                unlink($path); // Delete files
            }
        }
        
        rmdir($directoryPath); // Delete the now-empty directory
        
        return true;
    }
    
    /**
     * 
     * retrieves the URL of a presigned bucket file
     * 
     * @param string $filekey
     * @return string
     */
    public function getPresignedBucketFile(string $filekey){
        $cmd = $this->s3->getCommand('GetObject', [
            'Bucket' => self::BUCKET_NAME,
            'Key'    => $filekey
        ]);
        
        $request = $this->s3->createPresignedRequest($cmd, '+60 minutes');
        
        // Get the pre-signed URL
        return (string) $request->getUri();
    }
    
    /**
     * 
     * @param string $filekey
     * @return string
     */
    public function viewFile(string $filekey){        
        // Get the pre-signed URL
        $uri = (string) $this->getPresignedBucketFile($filekey);
        
        $mimeType = mime_content_type($filekey);
        
        header("Content-type: {$mimeType}");
        header("Content-Disposition: inline;filename=\"{$filekey}\"");
        
        return readfile($uri);
    }
    
    /**
     * 
     * @return AWSMangos3Bucket
     */
    public static function getInstance(){
        if(is_null(self::$instance)){
            self::$instance = new AWSMangos3Bucket();
        }
        
        return self::$instance;
    }
}

