<?php

/**
 * IBOS本地文件 处理类
 *
 * @author banyanCheung <banyan@ibos.com.cn>
 * @link http://www.ibos.com.cn/
 * @copyright Copyright &copy; 2012-2013 IBOS Inc
 */
/**
 * 本地文件处理类，基本上就是php文件函数的封装,实现IO接口
 *
 * @package ext.enginedriver.local
 * @author banyanCheung <banyan@ibos.com.cn>
 * @version $Id: file.php 3934 2014-08-11 09:32:26Z gzhzh $
 */

namespace application\core\engines\local;

use application\core\engines\FileOperationInterface;
use application\core\utils\Attach;
use application\core\utils\Cache;
use application\core\utils\Convert;
use application\core\utils\File;
use application\core\utils\Ibos;
use application\core\utils\Image;
use application\core\utils\Org;
use application\core\utils\StringUtil;
use application\extensions\ThinkImage\ThinkImage;
use application\modules\main\model\Attachment;
use application\modules\main\model\Setting;
use application\modules\user\model\BgTemplate;
use application\modules\user\utils\User as UserUtil;

class LocalFile implements FileOperationInterface
{

    public function __construct($config = array())
    {

    }

    private static $_instance;

    /**
     * 扫描文件夹时忽略的文件夹
     * @var array
     */
    public $excludeFiles = array('.svn', '.gitignore', '.', '..');

    public static function getInstance()
    {
        if (self::$_instance == null) {
            self::$_instance = new self;
        }
        return self::$_instance;
    }

    /**
     * 本地data文件夹文件的文件存在检测
     * 对应云平台的storage目录
     * @param string $file 文件名
     * @return boolean
     */
    public function fileExists($file)
    {
        return file_exists($file);
    }

    /**
     * 本地data文件夹的写操作
     * 对应云平台的storage目录
     * @param string $fileName
     * @param mixed $content
     * @return type
     */
    public function createFile($fileName, $content)
    {
        return file_put_contents($fileName, $content);
    }

    /**
     * 本地data文件夹的删除操作
     * 对应云平台的storage目录
     * @param string $fileName
     * @return boolean
     */
    public function deleteFile($fileName)
    {
        return @unlink($fileName);
    }

    /**
     * 本地文件名读取操作
     *
     * @param string $fileName
     * @param bool $suffix
     * @return string
     */
    public function fileName($fileName, $suffix = false)
    {
        $suffixStr = '';
        if (true === $suffix) {
            $suffixStr = '?' . VERHASH;
        }

        $host = rtrim(Ibos::app()->request->getHostInfo(), '/');
        return  $fileName . $suffixStr;
    }

    public function imageName($fileName)
    {
        return $this->fileName($fileName);
    }

    /**
     * 本地读取文件内容函数
     * @param string $fileName
     * @return string
     */
    public function readFile($fileName)
    {
        if (file_exists($fileName)) {
            return file_get_contents($fileName);
        }
        return false;
    }
    /**
     * 复制一个文件到另一个路径
     * @param string $source 原路径
     * @param string $savepath 目标路径
     * @param boolean $deleteSrc 是否删除原文件
     * @param boolean $deleteSrc 是否删除原文件
     * @return mixed
     */
    public function copyFile($source, $savepath, $deleteSrc = false)
    {
        $dir = substr($savepath, 0, strripos($savepath, '/'));
        if (!file_exists($dir)) {
            File::makeDirs($dir, 0777, true);
        }
        $isCopy = copy($source, $savepath);
        if (true === $deleteSrc) {
            $this->deleteFile($source);
        }
        if (false === $isCopy) {
            return false;
        }
        return $savepath;
    }

    /**
     * 本地环境文件大小：直接调用filesize
     * @param string $file 文件名
     * @return integer 文件大小字节数
     */
    public function fileSize($file)
    {
        return sprintf('%u', filesize($file));
    }

    /**
     * 本地环境图像尺寸获取：直接调用getimagesize
     * @param string $image 图像地址
     * @return mixed
     */
    public function imageSize($image)
    {
        if (filesize($image)) {
            return getimagesize($image);
        } else {
            return false;
        }
    }

    /**
     * 本地环境获取临时目录：返回data/temp目录
     * @return string
     */
    public function getTempPath()
    {
        return sprintf('%s', 'data/temp');
    }

    /**
     * 清空目录下文件
     * @param string $dir 目录名
     * @return void
     */
    public function clearDir($dir)
    {
        $directory = @dir($dir);
        if (is_object($directory)) {
            while ($entry = $directory->read()) {
                $file = $dir . DIRECTORY_SEPARATOR . $entry;
                if (is_file($file)) {
                    @unlink($file);
                }
            }
            $directory->close();
            @touch($dir . '/index.htm');
        }
    }

    /**
     * 递归清空目录包括目录本身
     * @param string $srcDir 目标文件夹路径
     */
    public function clearDirs($srcDir)
    {
        $dir = @opendir($srcDir);
        while ($entry = @readdir($dir)) {
            $file = $srcDir . DIRECTORY_SEPARATOR . $entry;
            if (!in_array($entry, $this->excludeFiles)) {
                if (is_dir($file)) {
                    $this->clearDirs($file . DIRECTORY_SEPARATOR);
                } else {
                    @unlink($file);
                }
            }
        }
        closedir($dir);
        @rmdir($srcDir);
    }

    /**
     * 本地环境附件下载方法
     * @param type $attach
     * @param type $downloadInfo
     */
    public function download($attach, $downloadInfo = array())
    {
        $file = PATH_ROOT . '/' . $attach['attachment'];
        if (file_exists($file)) {
            if (Ibos::app()->browser->name == 'msie' || Ibos::app()->browser->getVersion() == '10.0' || Ibos::app()->browser->getVersion() == '11.0'
            ) {
                $usingIe = true;
            } else {
                $usingIe = false;
            }
            $typeArr = array(
                '1' => "application/octet-stream",
                '3' => "application/msword",
                '4' => "application/msexcel",
                '5' => "application/mspowerpoint",
                '7' => "application/octet-stream",
                '8' => "application/x-shockwave-flash",
                '10' => "application/pdf",
                '11' => "application/octet-stream",
                '18' => "application/x-shockwave-flash"
            );
            $attachType = Attach::Attachtype(StringUtil::getFileExt($attach['filename']), 'id');
            $content = false;
            // 额外参数处理
            if (isset($downloadInfo['directView'])) {
                if (!in_array($attachType, array('1', '7', '8', '10'))) {
                    $content = true;
                }
                $contentType = $typeArr[$attachType];
            } else {
                if (in_array($attachType, array('3', '4', '5')) && $usingIe) {
                    $contentType = $typeArr[$attachType];
                } else {
                    $content = 1;
                    $contentType = "application/octet-stream";
                }
            }
            if (ob_get_length()) {
                ob_end_clean();
            }
            header("Cache-control: private");
            header("Content-type: {$contentType}");
            header("Accept-Ranges: bytes");
            header("Content-Length: " . sprintf("%u", $this->fileSize($file)));
            if ($usingIe) {
                $attach['filename'] = urlencode($attach['filename']);
            }
            $attach['filename'] = Convert::iIconv($attach['filename'], CHARSET, 'gbk');
            if ($content) {
                header("Content-Disposition: attachment; filename=\"" . $attach['filename'] . "\"");
            } else {
                header("Content-Disposition: filename=\"" . $attach['filename'] . "\"");
            }
            Attachment::model()->updateDownload($attach['aid']);
            readfile($file);
            exit();
        }
    }

    public function uploadFile($destFileName, $srcFileName)
    {
        $isUpload = move_uploaded_file($srcFileName, $destFileName);
        if ($isUpload) {
            return $destFileName;
        }

        if (rename($srcFileName, $destFileName)) {
            return $destFileName;
        }

        if (copy($srcFileName, $destFileName)) {
            return $destFileName;
        }

        return false;
    }

    public function createAvatar($srcPath, $params)
    {
        $avatarPath = 'data/avatar/';
        // 三种尺寸的地址
        $avatarBig = UserUtil::getAvatar($params['uid'], 'big');
        $avatarMiddle = UserUtil::getAvatar($params['uid'], 'middle');
        $avatarSmall = UserUtil::getAvatar($params['uid'], 'small');
        // 如果是本地环境，先确定文件路径要存在
        File::makeDirs($avatarPath . dirname($avatarBig));
        // 先创建空白文件
        $this->createFile($avatarPath . $avatarBig, '');
        $this->createFile($avatarPath . $avatarMiddle, '');
        $this->createFile($avatarPath . $avatarSmall, '');
        // 加载类库
        Ibos::import('ext.ThinkImage.ThinkImage', true);
        $imgObj = new ThinkImage(THINKIMAGE_GD);
        //裁剪原图
        $imgObj->open($srcPath)->crop($params['w'], $params['h'], $params['x'], $params['y'])->save($srcPath);
        //图片质量
        $qualitySize = Setting::model()->fetchSettingValueByKey('thumbquality');
        $imgObj->open($srcPath)->quality($srcPath, null, $qualitySize);
        //生成缩略图
        $imgObj->open($srcPath)->thumb(180, 180, 1)->save($avatarPath . $avatarBig);
        $imgObj->open($srcPath)->thumb(60, 60, 1)->save($avatarPath . $avatarMiddle);
        $imgObj->open($srcPath)->thumb(30, 30, 1)->save($avatarPath . $avatarSmall);
        return array(
            'avatar_big' => $avatarPath . $avatarBig,
            'avatar_middle' => $avatarPath . $avatarMiddle,
            'avatar_small' => $avatarPath . $avatarSmall,
        );
    }


    public function createBg($srcPath, $params)
    {
        $bgPath = 'data/home/';
        // 三种尺    寸的地址
        $bgBig = UserUtil::getBg($params['uid'], 'big');
//		$bgMiddle = UserUtil::getBg( $params['uid'], 'middle' );
        $bgSmall = UserUtil::getBg($params['uid'], 'small');
        File::makeDirs($bgPath . dirname($bgBig));
        // 先创建空白文件
        $this->createFile($bgPath . $bgBig, ' ');
//		$this->createFile( $bgPath . $bgMiddle, ' ' );
        $this->createFile($bgPath . $bgSmall, ' ');
        // 加载类库
        $imgObj = new ThinkImage(THINKIMAGE_GD);
        //裁剪原图(系统的背景图不需要裁剪)
        if (!isset($params['noCrop'])) {
            $imgObj->open($srcPath)->crop($params['w'], $params['h'], $params['x'], $params['y'], 1000, 300)->save($srcPath);
        }
        //图片质量
        $qualitySize = Setting::model()->fetchSettingValueByKey('thumbquality');
        $imgObj->open($srcPath)->quality($srcPath, null, $qualitySize);
        //生成缩略图
        $imgObj->open($srcPath)->thumb(1000, 300, 1)->save($bgPath . $bgBig);
        //$imgObj->open( $srcPath )->thumb( 520, 156, 1 )->save( $bgPath . $bgMiddle );
        $imgObj->open($srcPath)->thumb(400, 120, 1)->save($bgPath . $bgSmall);
        $host = $this->getImgHost($bgPath);
        // 设置为公用模板
        if (isset($params['commonSet']) && $params['commonSet']) {
            $this->setCommonBg($bgPath, $bgBig);
        }
        return array(
            'bg_big' => $host . $bgBig,
            'bg_middle' => '',
            'bg_small' => $host . $bgSmall,
        );
    }

    /**
     * 设置公用模板
     * @param string $src 图片路径
     * @return boolean
     */
    private function setCommonBg($bgPath, $bgBig)
    {
        $host = $this->getImgHost($bgPath);
        $data = array(
            'desc' => '',
            'status' => 0,
            'system' => 0,
            'image' => $host . $bgBig,
            'image_path' => $bgPath . $bgBig,
        );
        $addRes = BgTemplate::model()->add($data);
        return $addRes;
    }

    public function getImgHost($path)
    {
        return $path;
    }

    public function getHost($path)
    {
        return $path;
    }

    public function thumbnail($fromFileName, $toFileName, $thumbWidth = 96, $thumbHeight = 96)
    {
        Image::thumb($fromFileName, $toFileName, $thumbWidth, $thumbHeight);
        return $toFileName;
    }

    public function getOrgJs($typeArray)
    {
        $string = '';
        foreach ($typeArray as $type) {
            $js = $this->fileExists('data/org/' . $type . '.js');
            if (!$js) {
                Org::update($type);
            }
            $string .= '<script src = "data/org/' . $type . '.js?' . VERHASH . '" ></script>';
        }
        return $string;
    }

    public function setOrgJs($type, $value)
    {
        Cache::set($type . '_js', 1); //本地的话，直接引用js，所以只要设置这个cache存在就好了
        return $this->createFile(PATH_ROOT . '/data/org/' . $type . '.js', $value);
    }

    //tp的文字水印不支持透明度
    public function waterString($text, $size, $from, $to, $position, $alpha, $quality, $color, $fontPath)
    {
        $rgb = Convert::hexColorToRGB($color);
        Image::waterMarkString($text, $size, $from, $to, $position, $quality, $rgb, $fontPath);
    }

    //tp的图片水印
    public function waterPic($from, $pic, $to, $position, $alpha, $quality, $imgHeight, $imgWidth)
    {
        // 加载类库
        $imgObj = new ThinkImage(THINKIMAGE_GD);
        $imgObj->open($pic)->thumb($imgWidth, $imgHeight, 1)->save($pic);
        Image::water($from, $pic, $to, $position, $alpha, $quality);
    }

    /**
     * 读取一个网络文件到零时目录并生成临时文件
     * 备注：LocalFile 不需要获取网络文件的本地临时地址，这里只是做兼容处理。
     *
     * @param string $url 要读取的文件 URL
     * @param string $suffix 生成临时文件后缀，为空则自动读取
     * @return string
     */
    public function fetchTemp($url, $suffix = '')
    {
        if (empty($suffix)) {
            $suffix = pathinfo($url, PATHINFO_EXTENSION);
        }

        return $url . $suffix;
    }
}
