<?php
/*
 * The MIT License
 *
 * Copyright 2019 Blobt.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

namespace iron\actions;

use yii\base\Action;
use Yii;
use yii\base\Exception;
use yii\web\NotFoundHttpException;
use yii\web\Response;
use yii\web\ServerErrorHttpException;
use yii\web\UploadedFile;

/***
 * @author iron <weiriron@gmail.com>
 * @created Sep 11, 2019
 */
class UploadAction extends Action
{
    /**
     * 常量:表单数据类型
     */
    const DATA_TYPE_FORM = 1;
    /**
     * 常量: 二进制数据类型
     */
    const DATA_TYPE_BINARY = 2;
    /**
     * @var function
     *
     */
    public $saveInDatabase;
    /**
     * @var integer 限制的最大尺寸
     */
    public $maxSize;
    /**
     * @var array 允许的文件类型(扩展名)
     */
    public $allowType;
    /**
     * @var string 文件保存路径
     * template /image/jpg/
     */
    public $path;
    /**
     * @var string 数据类型
     */
    public $dataType;
    /**
     * @var bool 是否随机文件名(默认为随机,推荐为随机避免中文文件名导致的问题)
     */
    public $randName = true;
    /**
     * @var integer 默认单次最大上传数量(1-20)
     */
    public $maxCount;

    public function init()
    {
        if ($this->maxSize === null) {
            $this->maxSize = 2048;//默认最大尺寸为2M
        }
        if ($this->allowType === null) {
            $this->allowType = ['*'];//默认允许任何图片类型
        }
        if ($this->maxCount === null) {
            $this->maxCount = 5;//默认单次最大上传数量为5
        }
        if ($this->dataType === null) {
            $this->dataType = self::DATA_TYPE_FORM;//默认上传数据类型为表单数据
        }
    }

    public function run()
    {
        Yii::$app->response->format = Response::FORMAT_JSON;
        $data = [];
        try {
            if ($this->dataType == self::DATA_TYPE_FORM) {
                $file = UploadedFile::getInstanceByName('file');
                $this->checkType($file->extension);
                $this->checkSize($file->size);
                $savePath = $this->getSavePath();
                $fileName = $this->getFileName($file->baseName);
                $filePath = "$savePath$fileName.{$file->extension}";
                $file->saveAs($filePath);
//            $data[] = ["uploads/$this->path/$fileName.{$file->extension}"];
            } else {
                //TODO 非表单类型的文件上传
                throw new NotFoundHttpException('未实现');
//                $bin = Yii::$app->request->post('file');
//                $head = substr($bin, 0, 2);
//                $fileExtension = $this->getExtension($head);
//                $fileName = $this->getFileName();
//                $savePath = $this->getSavePath();
//                $filePath = "$savePath/$fileName.{$fileExtension}";
//                file_put_contents($filePath, $bin);
            }
            return ['status' => true, 'path' => "uploads/$this->path$fileName.{$file->extension}", 'alias' => $fileName . '.' . $file->extension];
        } catch (\Error $e) {
            throw new ServerErrorHttpException($e->getMessage());
//            return ['status' => false, 'info' => $e->getMessage()];
        }

    }

    protected function saveData()
    {

    }

    /**
     * 检查文件类型是否允许上传
     * @param $extension 文件扩展名
     * @return bool
     * @throws Exception
     */
    protected function checkType($extension)
    {
        if (in_array('*', $this->allowType)) {
            return true;
        }
        if (!in_array($extension, $this->allowType)) {
            throw new Exception("类型【{$extension}】不被允许,请在配置项中添加该类型");
        }
    }

    /**
     * 检查文件尺寸是否超过最大允许上传尺寸
     * @param $size 文件尺寸
     * @throws Exception
     */
    protected function checkSize($size)
    {
        if ($size / 1024 > $this->maxSize) {
            throw new Exception("文件大于允许的最大尺寸【{$this->maxSize}】,请修改配置或压缩文件");
        }
    }

    /**
     * 根据二进制流头大小判断文件类型
     * @param $head
     * @return mixed
     * @throws NotFoundHttpException
     */
    protected function getExtension($head)
    {
        $fileTypes = array(
            7790 => 'exe',
            7784 => 'midi',
            8297 => 'rar',
            255216 => 'jpg',
            7173 => 'gif',
            6677 => 'bmp',
            13780 => 'png'
        );
        if (isset($fileTypes[$head])) {
            return $fileTypes[$head];
        } else {
            throw new NotFoundHttpException('未找到该文件类型');
        }
    }

    /**
     * 获取文件保存路径并创建文件夹
     * @return string 文件保存的完成路径
     */
    protected function getSavePath()
    {
        $dirs = explode('/', $this->path);
        $savePath = Yii::getAlias('@app') . '/web/uploads';
        if (!is_dir($savePath)) {
            mkdir($savePath, 0755);
        }
        foreach ($dirs as $dir) {
            $savePath .= "/$dir";
            if (!is_dir($savePath)) {
                mkdir($savePath, 0755);
            }
        }
        return $savePath;
    }

    /**
     * 利用时间戳加随机数构建新文件名
     * @param $originName 源文件名
     * @return string
     */
    //TODO  利用原文件名生成新文件名
    protected function getFileName($originName = '')
    {
        return time() . rand(0, 9999);
    }
}