package com.zjty.tynotes.pas.base.response;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.util.Optional;

import static com.zjty.tynotes.pas.base.response.ResponseCode.*;


/**
 * Description : 结果类,用于统一返回格式 对外提供关于响应结果的很多便利的静态方法
 *
 * @author : M@tr!x [xhyrzldf@foxmail.com]
 * @Date : 2017/12/13 0:05
 */
@SuppressWarnings({"WeakerAccess", "unused"})
@Getter
@Setter
@ApiModel(value = "服务器返回体")
public class ServerResponse<T> {
    /**
     * 错误码
     */
    @ApiModelProperty(value = "返回码", example = "100")
    private Integer code;

    /**
     * 提示信息
     */
    @ApiModelProperty(value = "信息", example = "操作成功")
    private String msg;

    /**
     * 具体的内容
     */
    @ApiModelProperty(value = "返回数据")
    private T data;

    /* 以下为返回成功响应结果的各类重载静态方法 */

    public static <T> ServerResponse<T> success() {
        return new ServerResponse<>(OK.getCode(), OK.getMsg());
    }

    public static <T> ServerResponse<T> success(T data) {
        return new ServerResponse<>(OK.getCode(), OK.getMsg(), data);
    }

    public static <T> ServerResponse<T> success(String msg, T data) {
        return new ServerResponse<>(OK.getCode(), msg, data);
    }

    public static <T> ServerResponse<T> saveSuccess(T data) {
        return new ServerResponse<>(CREATED.getCode(), CREATED.getMsg(), data);
    }

    public static <T> ServerResponse<T> deleteSuccess() {
        return new ServerResponse<>(NO_CONTENT.getCode(), NO_CONTENT.getMsg());
    }

    public static <T> ServerResponse<T> deleteSuccessWithCount(Number effectCount) {
        return new ServerResponse<>(NO_CONTENT.getCode(), "删除成功,操作删除的数据条数为: " + effectCount);
    }

    public static <T> ServerResponse<T> deleteSuccessWithId(Number id) {
        return new ServerResponse<>(NO_CONTENT.getCode(), "删除成功,操作删除的数据id为: " + id);
    }

    public static <T> ServerResponse<T> uploadSuccess(T data) {
        return new ServerResponse<>(UPLOADED.getCode(), UPLOADED.getMsg(), data);
    }

    public static <T> ServerResponse<T> messageSuccess(String msg) {
        return new ServerResponse<>(OK.getCode(), msg);
    }

    /* 以下为返回失败响应结果的各类重载静态方法 */

    public static <T> ServerResponse<T> error() {
        return new ServerResponse<>(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
    }

    public static <T> ServerResponse<T> error(String errorMessage) {
        return new ServerResponse<>(INTERNAL_SERVER_ERROR.getCode(), errorMessage);
    }

    public static <T> ServerResponse<T> error(ResponseCode responseCode) {
        return new ServerResponse<>(responseCode.getCode(), responseCode.getMsg());
    }

    public static <T> ServerResponse<T> error(ResponseCode responseCode, String errorMessage) {
        return new ServerResponse<>(responseCode.getCode(), errorMessage);
    }

    public static <T> ServerResponse<T> error(ResponseCode responseCode, String errorMessage, T data) {
        return new ServerResponse<>(responseCode.getCode(), errorMessage, data);
    }

//    /* 以下为提供给CONTROL层向文件服务器操作文件获得相应结果的相关方法 */
//
//    /**
//     * <b>向文件服务器上传文件并且取得{@code {@link ServerResponse}}类型的响应结果</b>
//     * <p>
//     * <p>封装了control层的关于文件上传的代码
//     * <p>
//     * <p>例如file是a.txt,dirName=template, 在文件服务器上存放的位置就是{@code root(根目录)/template/a.txt }
//     *
//     * @param file    {@link MultipartFile} 接受到的文件俺对象
//     * @param dirName 在文件服务器上的文件夹名
//     * @return {@link ServerResponse} (包含了成功与导致失败的结果)
//     */
//    public static ServerResponse uploadAndGet(
//            @RequestParam("file") Optional<MultipartFile> file, String dirName) {
//        // 空指针判断
//        if (!file.isPresent()) return error(NOT_NULL_PARAMETER);
//        // 上传文件并且获得相应结果
//        MultipartFile uploadFile = file.get();
//        FileServerResponse fsp =
//                HttpClientUtil.uploadFileToServer(uploadFile, dirName, uploadFile.getOriginalFilename());
//        // 根据返回结果的状态码确定相应的返回信息(200返回成功,否则error)
//        return (fsp.getCode() == 200) ? uploadSuccess(fsp.getData()) : error(NO_CHANGED, fsp.getMsg());
//    }

//    /**
//     * <b>向文件服务器删除文件并且取得{@code {@link ServerResponse}}类型的响应结果</b>
//     * <p>
//     * <p>封装了control层的关于文件上传的代码
//     * <p>
//     * <p>例如提供的参数如下
//     * <li>fileName = reset-hv_20180115144834_wV9A9iVD.png
//     * <li>dirName = templates
//     * <li>那么实际删除的文件路径为: {@code root(根目录)/templates/reset-hv_20180115144834_wV9A9iVD.png}
//     *
//     * @param fileName 要删除的文件名<b>注意是文件服务器上的文件名,例如<b>reset-hv_20180115144834_wV9A9iVD.png</b> 格式为{@code
//     *                 原始文件名_timestamp_uuid8位}
//     * @param dirName  要删除的文件所处的文件目录
//     * @return {@link ServerResponse} (包含了成功与导致失败的结果)
//     */
//    public static ServerResponse deleteAndGet(
//            @RequestParam(value = "fileName") Optional<String> fileName, String dirName) {
//        // 空指针判断
//        if (!fileName.isPresent()) return error(NOT_NULL_PARAMETER);
//        // 发送删除文件的请求,附带文件所在的目录和在服务器中的文件名
//        FileServerResponse fsp = HttpClientUtil.daleteFileToServer(dirName, fileName.get());
//        // 根据返回结果的状态码确定相应的返回信息(200返回成功,否则error)
//        return (fsp.getCode() == 200) ? deleteSuccess() : error(NO_CHANGED, fsp.getMsg());
//    }

    /* 将构造器私有,防止外部进行实例化 仅提供给内部静态方法调用 * */
    private ServerResponse() {
    }

    private ServerResponse(Integer code) {
        this.code = code;
    }

    private ServerResponse(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    private ServerResponse(String msg, T data) {
        this.msg = msg;
        this.data = data;
    }

    private ServerResponse(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
}
