<?php

class File_Manager
{
    private $attachmentDir = "attachment";

    private $mimeConfig = array(
        "image/png" => "png",
        "image/jpeg" => "jpeg",
        "image/jpg" => "jpg",
        "image/gif" => "gif",
//        "image/bmp" => "bmp",
//        "audio/mp4" => "mp4",
//        "video/mp4" => "mp4",
    );

    private $defaultImgType = [
        "image/jpeg",
        "image/jpg",
        "image/png",
    ];

    public function __construct()
    {
        $this->wpf_Logger = new Wpf_Logger();
    }

    public function getPath($dateDir, $fileId, $isCreateFolder = true)
    {
        $fileId = str_replace("../", "", $fileId);
        $dateDir = str_replace("../", "", $dateDir);
        $dirName = WPF_LIB_DIR . "/../{$this->attachmentDir}/$dateDir";
        if (!is_dir($dirName) && $isCreateFolder) {
            mkdir($dirName, 0755, true);
        }
        return $dirName . "/" . $fileId;
    }

    public function readFile($fileId)
    {
        if (strlen($fileId) < 1) {
            return "";
        }
        // 需要hash目录，防止单目录文件过多
        $fileName = explode("-", $fileId);
        $dirName = $fileName[0];
        $fileId = $fileName[1];

        $path = $this->getPath($dirName, $fileId, false);
        return file_get_contents($path);
    }

    public function contentType($fileId)
    {
        if (strlen($fileId) < 1) {
            return "";
        }
        // 需要hash目录，防止单目录文件过多
        $fileName = explode("-", $fileId);
        $dirName = $fileName[0];
        $fileId = $fileName[1];
        $path = $this->getPath($dirName, $fileId);
        return mime_content_type($path);
    }

    public function saveFile($content)
    {
        $dateDir = date("Ymd");

        $fileName = sha1(uniqid());

        $path = $this->getPath($dateDir, $fileName);
        file_put_contents($path, $content);

        $mime = mime_content_type($path);

        if (!in_array($mime, $this->defaultImgType)) {
            throw new Exception("file type error");
        }

        $ext = isset($this->mimeConfig[$mime]) ? $this->mimeConfig[$mime] : "";
        if (false == empty($ext)) {
            $fileName = $fileName . "." . $ext;
            rename($path, $this->getPath($dateDir, $fileName));
        }

        return $dateDir . "-" . $fileName;
    }

    public function buildGroupAvatar($fileIdList = array())
    {
        if (empty($fileIdList)) {
            return "";
        }

        $picList = [];
        foreach ($fileIdList as $fileId) {
            $userAvatarPath = $this->turnFileId2FilePath($fileId);
            if (isset($userAvatarPath)) {
                $picList[] = $userAvatarPath;
            }
        }

        $dateDir = date("Ymd");
        $fileName = sha1(uniqid()) . "." . "jpeg";
        $groupImagePath = $this->getPath($dateDir, $fileName);

        $gorupAvatarPath = $this->splicingGroupAvatar($picList, $groupImagePath);

        if (empty($gorupAvatarPath)) {
            return null;
        }
        return $dateDir . "-" . $fileName;
    }

    /**
     * avatar from fileId to path
     * @param $fileId
     * @return string
     */
    private function turnFileId2FilePath($fileId)
    {
        $tag = __CLASS__ . "->" . __FUNCTION__;
        if (empty($fileId)) {
            return null;
        }
        try {
            $fileNameArray = explode("-", $fileId);
            $dirName = $fileNameArray[0];
            $fileName = $fileNameArray[1];
            return $this->getPath($dirName, $fileName);
        } catch (Exception $e) {
            $this->wpf_Logger->error($tag, $e->getMessage());
        }
        return null;
    }

    /**
     *
     * @param array $picList
     * @param $outImagePath
     * @return bool|string
     */
    private function splicingGroupAvatar($picList = array(), $outImagePath)
    {
        $tag = __CLASS__ . '-' . __FUNCTION__;
        if (!function_exists("imagecreatetruecolor")) {
            $this->wpf_Logger->error($tag, "php need support gd library, please check local php environment");
            return null;
        }

        if (empty($picList)) {
            return "";
        }

        $default_width = 500;
        $default_height = 500;

        $picList = array_slice($picList, 0, 9); // 只操作前9个图片

        $defaultImage = imagecreatetruecolor($default_width, $default_height); //创建图片大小

        //int imagecolorallocate ( resource $image , int $red , int $green , int $blue ) 为一幅图像分配颜色
        $color = imagecolorallocate($defaultImage, 229, 229, 229); // 为真彩色画布创建白色背景，再设置为透明
        imagefill($defaultImage, 0, 0, $color);      //区域填充
        imageColorTransparent($defaultImage, $color);     // 将某个颜色定义为透明色

        $pic_count = count($picList);
        $newLineArr = array();  // 需要换行的位置
        $space_x = 10;
        $space_y = 10;

        $start_x = 0;
        $start_y = 0;

        $picElements = [];

        switch ($pic_count) {
            case 1://ok
                $element = [
                    "x" => intval($default_width / 4),
                    "y" => intval($default_height / 4),
                    "w" => intval($default_width / 2),
                    "h" => intval($default_height / 2),
                ];
                $picElements[] = $element;
                break;
            case 2://ok
                $pic_w = intval($default_width / 2) - 5;//width
                $picElements = $this->buildImageElements(6, $start_x, $start_y, $pic_w, $default_height, [2]);
                break;
            case 3:
                $pic_w = intval($default_width / 2) - 5; // 宽度
                $pic_h = $default_height; // 高度

                for ($i = 0; $i < 3; $i++) {
                    $element = [
                        "x" => $start_x,
                        "y" => $start_y,
                        "w" => $pic_w,
                        "h" => $pic_h,
                    ];
                    $picElements[] = $element;

                    if ($i == 0) {
                        $pic_h = intval($pic_h / 2) - 5;
                        $start_x = $start_x + $pic_w + $space_x;
                    } else if ($i == 1) {
                        $start_y = $start_y + $pic_h + $space_y;
                    }
                }

                break;
            case 4: //OK
                $pic_w = intval($default_width / 2) - 5; // 宽度
                $pic_h = intval($default_height / 2) - 5; // 高度
                $picElements = $this->buildImageElements(6, $start_x, $start_y, $pic_w, $pic_h, [2]);
                break;
            case 5:
                $pic_w = intval($default_width / 2) - 5;
                $pic_h = intval($default_height / 2) - 5;

                $newLineArr = array(2);

                for ($i = 0; $i < 5; $i++) {

                    $element = [
                        "x" => $start_x,
                        "y" => $start_y,
                        "w" => $pic_w,
                        "h" => $pic_h,
                    ];
                    $picElements[] = $element;

                    if (in_array($i + 1, $newLineArr)) {
                        $start_x = 0;
                        $start_y = $start_y + $pic_h + $space_y;
                        $pic_w = intval($default_width / 3) - 5;
                    } else {
                        $start_x = $start_x + $pic_w + $space_x;
                    }
                }

                break;
            case 6://ok
                $pic_w = intval($default_width / 3) - 5; // 宽度
                $pic_h = intval($default_height / 2) - 5; // 高度
                $picElements = $this->buildImageElements(6, $start_x, $start_y, $pic_w, $pic_h, [3]);
                break;
            case 7://ok
                $start_x = 166.5;   // 开始位置X
                $pic_w = intval($default_width / 3) - 5; // 宽度
                $pic_h = intval($default_height / 3) - 5; // 高度
                $picElements = $this->buildImageElements(7, $start_x, $start_y, $pic_w, $pic_h, [1, 4]);
                break;
            case 8://ok
                $start_x = 80.5;   // 开始位置X
                $pic_w = intval($default_width / 3) - 5; // 宽度
                $pic_h = intval($default_height / 3) - 5; // 高度
                $picElements = $this->buildImageElements(8, $start_x, $start_y, $pic_w, $pic_h, [2, 5]);
                break;
            case 9://ok
                $pic_w = intval($default_width / 3) - 5; // 宽度
                $pic_h = intval($default_height / 3) - 5; // 高度
                $picElements = $this->buildImageElements(9, $start_x, $start_y, $pic_w, $pic_h, [3, 6]);
                break;
            default:
                return false;
        }


        //设置每张图片的尺寸
        foreach ($picList as $k => $pic_path) {
            $element = $picElements[$k];
            $resource = false;
            $mime = mime_content_type($pic_path);

            if ($mime == "image/jpg" | $mime == "image/jpeg") {
                $resource = imagecreatefromjpeg($pic_path);
            } else if ($mime == "image/png") {
                $resource = imagecreatefrompng($pic_path);
            } else {
                $this->wpf_Logger->error($tag, "unsupport image type [" . $mime . "]");
            }
            if ($resource == false) {
                continue;
            }
            // $start_x,$start_y copy图片在背景中的位置 0,0 被copy图片的位置   $pic_w,$pic_h copy后的高度和宽度
            imagecopyresized($defaultImage, $resource, $element['x'], $element['y'], 0, 0, $element['w'], $element['h'], imagesx($resource), imagesy($resource)); // 最后两个参数为原始图片宽度和高度，倒数两个参数为copy时的图片宽度和高度
        }

        header("Content-type: image/jpg");

        $res = imagejpeg($defaultImage, $outImagePath);

        // 释放内存
        imagedestroy($defaultImage);

        if (false === $res) {
            return false;
        }

        return $outImagePath;
    }

    /**
     * @param $imageSize
     * @param $start_x
     * @param $start_y
     * @param $pic_w
     * @param $pic_h
     * @param $newLineArr
     * @return array
     */
    private function buildImageElements($imageSize, $start_x, $start_y, $pic_w, $pic_h, $newLineArr)
    {
        $picElements = [];

        for ($i = 0; $i < $imageSize; $i++) {
            $element = [
                "x" => $start_x,
                "y" => $start_y,
                "w" => $pic_w,
                "h" => $pic_h,
            ];
            $picElements[] = $element;

            if (in_array($i + 1, $newLineArr)) {
                $start_x = 0;
                $start_y = $start_y + $pic_h + 10;
            } else {
                $start_x = $start_x + $pic_w + 10;
            }
        }

        return $picElements;
    }
}