<?php

namespace admin\action;

use model\file;

/**
 * Class uploadAction
 * @package admin\action
 */
class uploadAction  extends \action
{

    /**
     * 源文件的pathinfo
     * @var array
     */
    private $filePathInfo;

    /**
     * 文件限制类型
     * @var array
     */
    private $fileType = [];

    /**
     * 当前是第几块
     * @var int
     */
    private $index = 0;

    /**
     * 总共多少块
     * @var int
     */
    private $total = 0;

    /**
     * 上传文件的文件大小
     * @var int
     */
    private $fileSize = 0;

    /**
     * 新文件的BaseName名称
     * @var string
     */
    private $newFileBaseName;

    /**
     * 原文件
     * @var string
     */
    private $originalName;

    /**
     * uploadAction constructor.
     */
    public function __construct()
    {
        if(isset(\mvc::$cfg['upload']['type'])) $this->fileType = \mvc::$cfg['upload']['type'];
    }

    /**
     * 大文件上传
     */
    public function uploadBigFile()
    {
        ignore_user_abort(true);
        set_time_limit(500);
        $result = null;
        $req = \mvc::$req;
        $type = $req['type'];

        $reqfiles = \mvc::$reqfiles;
        $uploadID = empty($req['uploadId']) ? str_replace('.','',uniqid('',true)) : $req['uploadId'];

        $extname = strtolower(pathinfo($req['filename'], PATHINFO_EXTENSION));
        if(isset(\mvc::$cfg['upload']['type']) && !in_array($extname,\mvc::$cfg['upload']['type']) )
        {
            echo json_encode([
                'code' => 1001,
                "msg" => lg("非法的文件类型").": ".$req['filename']
            ]);
            exit();
        }
        $dir = \mvc::$cfg['dir']['files'].DIRECTORY_SEPARATOR.$type.DIRECTORY_SEPARATOR.date('Ym').DIRECTORY_SEPARATOR.substr($uploadID, -1);
        mkdirs($dir,'0777');
        mkdirs($dir,0777);
        $filename_tmp = $dir.DIRECTORY_SEPARATOR.$uploadID.".".$extname.".tmp";
        $filename = substr($filename_tmp,0,-4);
        $fdata = $reqfiles['data'];
        $fp = fopen($fdata["tmp_name"],"r");
        $filedata = fread($fp,filesize($fdata["tmp_name"]));
        fclose($fp);
        $f = null;

        if($req['index'] == 0)
        {
            if(file_exists($filename_tmp)) @unlink($filename_tmp);
            $f = fopen($filename_tmp,"a");
        }
        if(file_exists($filename_tmp))
        {
            if(is_null($f)) $f = fopen($filename_tmp,"a");
            fwrite($f,$filedata);
            fclose($f);
        }
        if($req['index'] == $req['total'])
        {
            rename($filename_tmp, $filename);
            if(!empty($req['callAction']))
            {
                call($req['callAction'], [
                    'filename' => $filename,
                    "extname" => $extname,
                    'userFilename' => $req['filename']
                ]);
            }
            $result = [
                'code'=> 0,
                'rows'=>[
                    'uploadID' => $uploadID,
                    'index' => $req['index'] * 1,
                    'filename' => basename($filename)
                ]
            ];
        }
        if(is_null($result)){
            $result = [
                'code' => 0,
                'rows' => [
                    'index' => $req['index'] * 1,
                    'uploadID' => $uploadID,
                    'filename' => basename($filename)
                ]
            ];
        }
        echo json_encode($result);
        exit();
    }

    /**
     * 接受处理上传文件
     * @author YangXing
     */
    public function upload()
    {
        $this->header();
        $file = \mvc::$reqfiles;
        //获得原文件名称
        $this->originalName = isset(\mvc::$req['filename']) ? \mvc::$req['filename'] : null;//原文件名
        $this->filePathInfo = pathinfo($this->originalName);
        $this->newFileBaseName = empty(\mvc::$req['new_file_base_name']) ? $this->getBaseFileName() : \mvc::$req['new_file_base_name'];
        if(isset(\mvc::$req['total']))  $this->total = \mvc::$req['total']; //当前总块数
        if(isset(\mvc::$req['index'])) $this->index = \mvc::$req['index']; //当前片数
        if(isset(\mvc::$req['size'])) $this->fileSize = \mvc::$req['size']; //文件的总大小
        if(!$file || !$this->originalName) $this->msgJson('没有文件');
        //判断文件类型
        $this->judgmentType();
        //上传文件的路径
        $newFileName = $this->getDir($this->newFileBaseName).$this->newFileBaseName.'.'.$this->filePathInfo['extension'];
        // 清除文件状态
        clearstatcache($newFileName);
        // 这里判断有没有上传的文件流
        if ($file['data']['error'] == 0)
        {
            // 如果文件不存在，就创建
            if (!file_exists($newFileName))
            {
                //新文件不存在,把临时文件移动到新文件
                if (!move_uploaded_file($file['data']['tmp_name'], $newFileName))
                {
                    $this->msgJson(lg('无法移动文件'));
                }
                // 片数相等，等于完成了
                $this->isSuccessful();
            }
            // 如果当前片数小于等于总片数,就在文件后继续添加
            if($this->index <= $this->total)
            {
                //以追加(独占锁)的形式把新传入的文件块写入文件中
                if (!file_put_contents($newFileName, file_get_contents($file['data']['tmp_name']), FILE_APPEND|LOCK_EX))
                {
                    $this->msgJson(lg('无法写入文件'));
                }
                // 片数相等，等于完成了
                $this->isSuccessful();
            }
        } else {
            $this->msgJson(lg('没有上传文件'));
        }
    }


    /**
     * 获取新的FileBaseName
     * @return array|string|string[]
     */
    public function getBaseFileName()
    {
        return str_replace('.','',uniqid('',true));
    }

    //设置header
    private function header()
    {
        header('Access-Control-Allow-Origin:*');
        header('Access-Control-Allow-Methods:PUT,POST,GET,DELETE,OPTIONS');
        header('Access-Control-Allow-Headers:x-requested-with,content-type');
        header('Content-Type:application/json; charset=utf-8');
    }

    /**
     * 转换数据库可以存储的格式
     * @param $dir
     * @return array|string|string[]
     */
    public function dirFormat($dir)
    {
        return str_replace(\mvc::$cfg['dir']['files'],'',$dir);
    }

    /**
     * 获取绝对路径地址
     * @param $uploadID
     * @return string
     */
    public function getDir($uploadID)
    {
        $dir = \mvc::$cfg['dir']['files'];
        $dir .= '/';
        $dir .= \mvc::$req['catalogue'];
        $dir .= '/';
        $dir .= date('Ym');
        $dir .= '/';
        $dir .= substr($uploadID, -1);
        $dir .= '/';
        mkdirs($dir,0777);
        return $dir;
    }

    /**
     * TODO 前端可以传size 过来验证是否传输完整
     * 当前块等于总块数就成功了
     * @return bool
     */
    private function isSuccessful()
    {
        if($this->index == $this->total){

            $fileName =  $this->getDir($this->newFileBaseName).$this->newFileBaseName.'.'.$this->filePathInfo['extension'];
            //添加到files表中
            $id = (new file())->add($this->dirFormat($fileName),basename($this->originalName),$this->isImage($fileName));
            $param = [
                'file_name' => $fileName,
                'file_id' => $id,
                'file_base_name' => $this->dirFormat($fileName),
                'param' => \mvc::$req['param']
            ];
            $config = $this->__getConfig(\mvc::$req['config_key']);
            if(isset($config['model'])){
                (new $config['model']())->save($param,$config);
            }
        }
        $result = [
            'code' => 0,
            'rows' => [
                'index' => $this->index * 1,
                'new_file_base_name' => $this->newFileBaseName,
                'filename' => basename($this->originalName),
            ]
        ];
        echo json_encode($result);exit;
    }

    /**
     * @param $fileName
     * @return string
     */
    private function isImage($fileName)
    {
        $result = exif_imagetype($fileName);
        return $result === false ? 'files' : 'image';
    }

    /**
     * 判断文件类型是否支持
     * @return bool
     */
    private function judgmentType()
    {
        if(!empty($this->fileType))
        {
            if(isset($this->filePathInfo['extension'])
                && !in_array($this->filePathInfo['extension'],\mvc::$cfg['upload']['type']))
            {
                $this->msgJson(lg("非法的文件类型").": ".\mvc::$req['file_name']);
            }
        }
        return true;
    }

    /**
     * @param $type
     * @return array
     */
    private function __getConfig($type)
    {
        $config = [
            'init' => [
                'url' => '/pro/pic/list?type=init&key=', //在前端拼上
                'qty' => 5,
                'catalogue' => 'pro', //文件目录
                'is_image_more' => true,
                'model' => \model\pro\pic::class,
                'button' => [
                    ['name' => lg('删除'),'class' => 'btn btn-outline-primary btn-delete btn-deletes btn-sm fa fa-remove','callback' => 'deletes'],
                    ['name' => lg('设为主图'),'class'=> 'btn btn-outline-primary btn-setMaster btn-white btn-sm','callback' => 'setMaster'],
                    ['name' => lg('审核'),'class' => 'btn btn-outline-primary btn-examine btn-white btn-sm','callback' => 'examine']
                ],
                'maxnumber' => 20,
                'is_image' => true,
                'accept' => 'image/jpeg,image/png,image/gif',
            ],
            'beautify'=> [
                'url' => '/pro/pic/list?type=beautify&key=', //在前端拼上
                'qty' => 5,
                'catalogue' => 'pro',
                'is_image_more' => true,
                'model' => \model\pro\pic::class,
                'button' => [
                    ['name' => lg('删除'),'class' => 'btn btn-outline-primary btn-delete btn-deletes btn-sm fa fa-remove','callback' => 'deletes'],
                    ['name' => lg('设为主图'),'class'=> 'btn btn-outline-primary btn-setMaster btn-white btn-sm','callback' => 'setMaster'],
                    ['name' => lg('审核'),'class' => 'btn btn-outline-primary btn-examine btn-white btn-sm','callback' => 'examine']
                ],
                'is_image' => true,
                'accept' => 'image/jpeg,image/png,image/gif',
            ],
            'attach' => [
                'url' => '/pro/pic/list?type=attach&key=', //在前端拼上
                'qty' => 5,
                'is_image_more' => true,
                'model' => \model\pro\pic::class,
                'catalogue' => 'pro', //文件目录
                'is_image' => 1,
                'button' => [
                    ['name' => lg('删除'),'class' => 'btn btn-outline-primary btn-delete btn-deletes btn-sm fa fa-remove','callback' => 'deletes'],
                ],
                'accept' => 'image/jpeg,image/png,image/gif',
            ],
            'notcattle'=> [
                'url' => '/pro/pic/list?type=notcattle&key=', //在前端拼上
                'qty' => 1,
                'is_image_more' => false,
                'model' => \model\pro\pic::class,
                'is_image' => 1,
                'catalogue' => 'pro', //文件目录
                'button' => [
                    ['name' => lg('删除'),'class' => 'btn btn-outline-primary btn-delete btn-deletes btn-sm fa fa-remove','callback' => 'deletes'],
                ],
                'accept' => 'image/jpeg,image/png,image/gif',
            ],
            '360'=> [
                'url' => '/pro/pic/list?type=360&key=', //在前端拼上
                'qty' => 5,
                'catalogue' => 'pro',
                'is_image_more' => true,
                'is_image' => 0,
                'model' => \model\pro\pic::class,
                'button' => [
                    ['name' => lg('删除'),'class' => 'btn btn-outline-primary btn-delete btn-deletes btn-sm fa fa-remove','callback' => 'deletes'],
                ],
                'accept' => 'xls,xlsx,txt,tif,doc,docx,zip,rar,jpeg,jpg,gif,bmp,png,tiff,pdf'
            ],
            'other'=> [
                'url' => '/pro/pic/list?type=other&key=', //在前端拼上
                'qty' => 5,
                'catalogue' => 'pro',
                'is_image_more' => true,
                'is_image' => 0,
                'model' => \model\pro\pic::class,
                'button' => [
                    ['name' => lg('删除'),'class' => 'btn btn-outline-primary btn-delete btn-deletes btn-sm fa fa-remove','callback' => 'deletes'],
                ],
                'accept' => 'xls,xlsx,txt,tif,doc,docxzip,rar,jpeg,jpg,gif,bmp,png,tiff,pdf'
            ],
            'param-image' => [
                'url' => '/pro/param/imageList?key=', //在前端拼上
                'qty' => 1,
                'is_image_more' => false,
                'model' => \model\pro\cate::class,
                'is_image' => 1,
                'catalogue' => 'pro', //文件目录
                'button' => [
                    ['name' => lg('删除'),'class' => 'btn btn-outline-primary btn-delete btn-deletes btn-sm fa fa-remove','callback' => 'deletes'],
                ],
                'accept' => 'image/jpeg,image/png,image/gif',
            ]
        ];
        return $config[$type];
    }

    /**
     * @param $type
     */
    public function getConfig($type)
    {
        $this->successJson($this->__getConfig($type));
    }

}