<?php

namespace apexl\Io\includes;

use apexl\Config\Singleton;
use Slim\Psr7\UploadedFile;

class Utils
{
    const HIDE_FROM_DISPLAY = 'eDisplayNone';

    /**
     * Moves the uploaded file to the upload directory and assigns it a unique name
     * to avoid overwriting an existing uploaded file.
     *
     * @param string $directory directory to which the file is moved
     * @param UploadedFile $uploadedFile file uploaded file to move
     * @throws \Exception
     * @return string filename of moved file
     */
    public static function moveUploadedFile($directory, UploadedFile $uploadedFile)
    {
        //can't move the file if the key is not st in config, throw an error.
        $config = Singleton::getInstance();

        if(!isset($config->app->fileUploadDirectory)){
            throw new \Exception('The required configuration for fileUploadDirectory ({"app": {"fileUploadDirectory": "path/to/dir"}} is not defined');
        }

        $filename = $uploadedFile->getClientFilename();

        $basePath = System::getBasePath();
        $directory = $config->app->fileUploadDirectory.DIRECTORY_SEPARATOR.$directory;
        $filePath = $directory.DIRECTORY_SEPARATOR. $filename;

        self::createPath($basePath.DIRECTORY_SEPARATOR.$directory);
        $uploadedFile->moveTo($basePath.DIRECTORY_SEPARATOR.$filePath);

        return $filePath;
    }

    /**
     * @param $data
     * @param $filename
     * @param $directory
     * @return false|int
     * @throws \Exception
     */
    public static function writeDataToFile($data, $filename, $directory){
        //can't save the file if the key is not st in config, throw an error.
        $config = Singleton::getInstance();

        if(!isset($config->app->fileUploadDirectory)){
            throw new \Exception('The required configuration for fileUploadDirectory ({"app": {"fileUploadDirectory": "path/to/dir"}} is not defined');
        }

        $basePath = System::getBasePath();

        $directory = $config->app->fileUploadDirectory.DIRECTORY_SEPARATOR.$directory;
        $filePath = $directory.DIRECTORY_SEPARATOR. $filename;

        self::createPath($basePath.DIRECTORY_SEPARATOR.$directory);
        $written = file_put_contents($basePath.DIRECTORY_SEPARATOR.$filePath, $data);
        return $written;
    }

    /**
     * @param $directory
     * @param $oldname
     * @param $newname
     * @return bool
     * @throws \Exception
     */
    public static function renameFile($directory, $oldname, $newname){
        //can't move the file if the key is not st in config, throw an error.
        $config = Singleton::getInstance();
        if(!isset($config->app->fileUploadDirectory)){
            throw new \Exception('The required configuration for fileUploadDirectory ({"app": {"fileUploadDirectory": "path/to/dir"}} is not defined');
        }

        $basePath = System::getBasePath();
        return rename($basePath.DIRECTORY_SEPARATOR.$config->app->fileUploadDirectory.DIRECTORY_SEPARATOR.$directory .DIRECTORY_SEPARATOR. $oldname, $basePath.DIRECTORY_SEPARATOR.$config->app->fileUploadDirectory.DIRECTORY_SEPARATOR.$directory .DIRECTORY_SEPARATOR. $newname);
    }

    /**
     * @param $path
     * @return bool
     */
    public static function createPath($path) {
        if (is_dir($path)) return true;
        $prev_path = substr($path, 0, strrpos($path, DIRECTORY_SEPARATOR, -2) + 1 );
        $return = self::createPath($prev_path);
        return ($return && is_writable($prev_path)) ? mkdir($path) : false;
    }

    public static function getFilesInDir($dir){
        $config = Singleton::getInstance();
        //can't move the file if the key is not st in config, throw an error.
        if(!isset($config->app->fileUploadDirectory)){
            throw new \Exception('The required configuration for fileUploadDirectory ({"app": {"fileUploadDirectory": "path/to/dir"}} is not defined');
        }
        $files = [];
        $basePath = System::getBasePath().DIRECTORY_SEPARATOR.$config->app->fileUploadDirectory;
        if ($handle = opendir($basePath.DIRECTORY_SEPARATOR.$dir)) {
            while (false !== ($entry = readdir($handle))) {
                if ($entry != "." && $entry != "..") {
                    $files[] = $config->app->fileUploadDirectory.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.$entry;
                }
            }
            closedir($handle);
        }
        return $files;
    }

    /**
     * Known file mime types
     * @todo allow native additions to this without changing core. Perhaps from config?
     * @return string[]
     */
    public static function mimeMap(){
        return [
            'video/3gpp2'                                                               => '3g2',
            'video/3gp'                                                                 => '3gp',
            'video/3gpp'                                                                => '3gp',
            'application/x-compressed'                                                  => '7zip',
            'audio/x-acc'                                                               => 'aac',
            'audio/ac3'                                                                 => 'ac3',
            'application/postscript'                                                    => 'ai',
            'audio/x-aiff'                                                              => 'aif',
            'audio/aiff'                                                                => 'aif',
            'audio/x-au'                                                                => 'au',
            'video/x-msvideo'                                                           => 'avi',
            'video/msvideo'                                                             => 'avi',
            'video/avi'                                                                 => 'avi',
            'application/x-troff-msvideo'                                               => 'avi',
            'application/macbinary'                                                     => 'bin',
            'application/mac-binary'                                                    => 'bin',
            'application/x-binary'                                                      => 'bin',
            'application/x-macbinary'                                                   => 'bin',
            'image/bmp'                                                                 => 'bmp',
            'image/x-bmp'                                                               => 'bmp',
            'image/x-bitmap'                                                            => 'bmp',
            'image/x-xbitmap'                                                           => 'bmp',
            'image/x-win-bitmap'                                                        => 'bmp',
            'image/x-windows-bmp'                                                       => 'bmp',
            'image/ms-bmp'                                                              => 'bmp',
            'image/x-ms-bmp'                                                            => 'bmp',
            'application/bmp'                                                           => 'bmp',
            'application/x-bmp'                                                         => 'bmp',
            'application/x-win-bitmap'                                                  => 'bmp',
            'application/cdr'                                                           => 'cdr',
            'application/coreldraw'                                                     => 'cdr',
            'application/x-cdr'                                                         => 'cdr',
            'application/x-coreldraw'                                                   => 'cdr',
            'image/cdr'                                                                 => 'cdr',
            'image/x-cdr'                                                               => 'cdr',
            'zz-application/zz-winassoc-cdr'                                            => 'cdr',
            'application/mac-compactpro'                                                => 'cpt',
            'application/pkix-crl'                                                      => 'crl',
            'application/pkcs-crl'                                                      => 'crl',
            'application/x-x509-ca-cert'                                                => 'crt',
            'application/pkix-cert'                                                     => 'crt',
            'text/css'                                                                  => 'css',
            'text/x-comma-separated-values'                                             => 'csv',
            'text/comma-separated-values'                                               => 'csv',
            'application/vnd.msexcel'                                                   => 'csv',
            'text/csv'                                                                  => 'csv',
            'application/x-director'                                                    => 'dcr',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document'   => 'docx',
            'application/x-dvi'                                                         => 'dvi',
            'message/rfc822'                                                            => 'eml',
            'application/x-msdownload'                                                  => 'exe',
            'video/x-f4v'                                                               => 'f4v',
            'audio/x-flac'                                                              => 'flac',
            'video/x-flv'                                                               => 'flv',
            'image/gif'                                                                 => 'gif',
            'application/gpg-keys'                                                      => 'gpg',
            'application/x-gtar'                                                        => 'gtar',
            'application/x-gzip'                                                        => 'gzip',
            'application/mac-binhex40'                                                  => 'hqx',
            'application/mac-binhex'                                                    => 'hqx',
            'application/x-binhex40'                                                    => 'hqx',
            'application/x-mac-binhex40'                                                => 'hqx',
            'text/html'                                                                 => 'html',
            'image/x-icon'                                                              => 'ico',
            'image/x-ico'                                                               => 'ico',
            'image/vnd.microsoft.icon'                                                  => 'ico',
            'text/calendar'                                                             => 'ics',
            'application/java-archive'                                                  => 'jar',
            'application/x-java-application'                                            => 'jar',
            'application/x-jar'                                                         => 'jar',
            'image/jp2'                                                                 => 'jp2',
            'video/mj2'                                                                 => 'jp2',
            'image/jpx'                                                                 => 'jp2',
            'image/jpm'                                                                 => 'jp2',
            'image/jpeg'                                                                => 'jpeg',
            'image/pjpeg'                                                               => 'jpeg',
            'application/x-javascript'                                                  => 'js',
            'application/json'                                                          => 'json',
            'text/json'                                                                 => 'json',
            'application/vnd.google-earth.kml+xml'                                      => 'kml',
            'application/vnd.google-earth.kmz'                                          => 'kmz',
            'text/x-log'                                                                => 'log',
            'audio/x-m4a'                                                               => 'm4a',
            'audio/mp4'                                                                 => 'm4a',
            'application/vnd.mpegurl'                                                   => 'm4u',
            'audio/midi'                                                                => 'mid',
            'application/vnd.mif'                                                       => 'mif',
            'video/quicktime'                                                           => 'mov',
            'video/x-sgi-movie'                                                         => 'movie',
            'audio/mpeg'                                                                => 'mp3',
            'audio/mpg'                                                                 => 'mp3',
            'audio/mpeg3'                                                               => 'mp3',
            'audio/mp3'                                                                 => 'mp3',
            'video/mp4'                                                                 => 'mp4',
            'video/mpeg'                                                                => 'mpeg',
            'application/oda'                                                           => 'oda',
            'audio/ogg'                                                                 => 'ogg',
            'video/ogg'                                                                 => 'ogg',
            'application/ogg'                                                           => 'ogg',
            'application/x-pkcs10'                                                      => 'p10',
            'application/pkcs10'                                                        => 'p10',
            'application/x-pkcs12'                                                      => 'p12',
            'application/x-pkcs7-signature'                                             => 'p7a',
            'application/pkcs7-mime'                                                    => 'p7c',
            'application/x-pkcs7-mime'                                                  => 'p7c',
            'application/x-pkcs7-certreqresp'                                           => 'p7r',
            'application/pkcs7-signature'                                               => 'p7s',
            'application/pdf'                                                           => 'pdf',
            'application/octet-stream'                                                  => 'pdf',
            'application/x-x509-user-cert'                                              => 'pem',
            'application/x-pem-file'                                                    => 'pem',
            'application/pgp'                                                           => 'pgp',
            'application/x-httpd-php'                                                   => 'php',
            'application/php'                                                           => 'php',
            'application/x-php'                                                         => 'php',
            'text/php'                                                                  => 'php',
            'text/x-php'                                                                => 'php',
            'application/x-httpd-php-source'                                            => 'php',
            'image/png'                                                                 => 'png',
            'image/x-png'                                                               => 'png',
            'application/powerpoint'                                                    => 'ppt',
            'application/vnd.ms-powerpoint'                                             => 'ppt',
            'application/vnd.ms-office'                                                 => 'ppt',
            'application/msword'                                                        => 'ppt',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
            'application/x-photoshop'                                                   => 'psd',
            'image/vnd.adobe.photoshop'                                                 => 'psd',
            'audio/x-realaudio'                                                         => 'ra',
            'audio/x-pn-realaudio'                                                      => 'ram',
            'application/x-rar'                                                         => 'rar',
            'application/rar'                                                           => 'rar',
            'application/x-rar-compressed'                                              => 'rar',
            'audio/x-pn-realaudio-plugin'                                               => 'rpm',
            'application/x-pkcs7'                                                       => 'rsa',
            'text/rtf'                                                                  => 'rtf',
            'text/richtext'                                                             => 'rtx',
            'video/vnd.rn-realvideo'                                                    => 'rv',
            'application/x-stuffit'                                                     => 'sit',
            'application/smil'                                                          => 'smil',
            'text/srt'                                                                  => 'srt',
            'image/svg+xml'                                                             => 'svg',
            'application/x-shockwave-flash'                                             => 'swf',
            'application/x-tar'                                                         => 'tar',
            'application/x-gzip-compressed'                                             => 'tgz',
            'image/tiff'                                                                => 'tiff',
            'text/plain'                                                                => 'txt',
            'text/x-vcard'                                                              => 'vcf',
            'application/videolan'                                                      => 'vlc',
            'text/vtt'                                                                  => 'vtt',
            'audio/x-wav'                                                               => 'wav',
            'audio/wave'                                                                => 'wav',
            'audio/wav'                                                                 => 'wav',
            'application/wbxml'                                                         => 'wbxml',
            'video/webm'                                                                => 'webm',
            'audio/x-ms-wma'                                                            => 'wma',
            'application/wmlc'                                                          => 'wmlc',
            'video/x-ms-wmv'                                                            => 'wmv',
            'video/x-ms-asf'                                                            => 'wmv',
            'application/xhtml+xml'                                                     => 'xhtml',
            'application/excel'                                                         => 'xl',
            'application/msexcel'                                                       => 'xls',
            'application/x-msexcel'                                                     => 'xls',
            'application/x-ms-excel'                                                    => 'xls',
            'application/x-excel'                                                       => 'xls',
            'application/x-dos_ms_excel'                                                => 'xls',
            'application/xls'                                                           => 'xls',
            'application/x-xls'                                                         => 'xls',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'         => 'xlsx',
            'application/vnd.ms-excel'                                                  => 'xlsx',
            'application/xml'                                                           => 'xml',
            'text/xml'                                                                  => 'xml',
            'text/xsl'                                                                  => 'xsl',
            'application/xspf+xml'                                                      => 'xspf',
            'application/x-compress'                                                    => 'z',
            'application/x-zip'                                                         => 'zip',
            'application/zip'                                                           => 'zip',
            'application/x-zip-compressed'                                              => 'zip',
            'application/s-compressed'                                                  => 'zip',
            'multipart/x-zip'                                                           => 'zip',
            'text/x-scriptzsh'                                                          => 'zsh',
        ];
    }
    public static function mime2ext($mime) {
        $mime_map = self::mimeMap();
        return isset($mime_map[$mime]) ? $mime_map[$mime] : false;
    }

    public static function ext2mime($ext){
        return array_search(ltrim($ext,'.'), self::mimeMap());
    }
    public static function downloadFile($file_url, $name, $contentType = 'application/octet-stream'){
        header('Content-Type: '.$contentType);
        header("Content-Transfer-Encoding: Binary");
        header("Content-disposition: attachment; filename=\"" . basename($name) . "\"");
        ob_clean(); flush();
        readfile($file_url);
        exit;
    }

    /**
     * @return void
     * @throws \Exception
     */
    public static function reloadConfig(){
        (Singleton::getInstance())->reloadConfig();
    }

    /**
     * @param $string
     * @return string
     * @see https://stackoverflow.com/a/14114443/2412837
     */
    public static function hyphenize($string) {
        $dict = array(
            "I'm"      => "I am",
            "thier"    => "their",
            // Add your own replacements here
        );
        return strtolower(
            preg_replace(
                array( '#[\\s-]+#', '#[^A-Za-z0-9. -]+#' ),
                array( '-', '' ),
                // the full cleanString() can be downloaded from http://www.unexpectedit.com/php/php-clean-string-of-utf8-chars-convert-to-similar-ascii-char
                self::cleanString(
                    str_replace( // preg_replace can be used to support more complicated replacements
                        array_keys($dict),
                        array_values($dict),
                        urldecode($string)
                    )
                )
            )
        );
    }

    /**
     * @param $text
     * @return array|string|string[]|null
     */
    public static function cleanString($text) {
        $utf8 = array(
            '/[áàâãªä]/u'   =>   'a',
            '/[ÁÀÂÃÄ]/u'    =>   'A',
            '/[ÍÌÎÏ]/u'     =>   'I',
            '/[íìîï]/u'     =>   'i',
            '/[éèêë]/u'     =>   'e',
            '/[ÉÈÊË]/u'     =>   'E',
            '/[óòôõºö]/u'   =>   'o',
            '/[ÓÒÔÕÖ]/u'    =>   'O',
            '/[úùûü]/u'     =>   'u',
            '/[ÚÙÛÜ]/u'     =>   'U',
            '/ç/'           =>   'c',
            '/Ç/'           =>   'C',
            '/ñ/'           =>   'n',
            '/Ñ/'           =>   'N',
            '/–/'           =>   '-', // UTF-8 hyphen to "normal" hyphen
            '/[’‘‹›‚]/u'    =>   ' ', // Literally a single quote
            '/[“”«»„]/u'    =>   ' ', // Double quote
            '/ /'           =>   ' ', // nonbreaking space (equiv. to 0x160)
        );
        return preg_replace(array_keys($utf8), array_values($utf8), $text);
    }

    /**
     * @param $var
     * @param null $ob_ar
     * @return bool
     */
    public static function checkExistsAndNotEmpty($var, $ob_ar = NULL)
    {
        if($ob_ar){
            if(is_array($ob_ar)){
                return isset($ob_ar[$var]) && !empty($ob_ar[$var]);
            } elseif (is_object($ob_ar)){
                return isset($ob_ar->$var) && !empty($ob_ar->$var);
            }
        }
        return isset($var) && !empty($var);
    }
}