package com.hdkj.hussar;


import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Optional;

import lombok.Getter;
import lombok.Setter;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;

@Setter
@Getter
@ApiModel(description = "响应信息主体")
public class ApiResponse<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(
            value = "状态码",
            required = true
    )
    private int code;
    @ApiModelProperty(
            value = "是否成功",
            required = true
    )
    private boolean success;
    @ApiModelProperty("承载数据")
    private T data;
    @ApiModelProperty(
            value = "返回消息",
            required = true
    )
    private String msg;

    private ApiResponse(IResultCode resultCode) {
        this(resultCode, null, resultCode.getMessage());
    }

    private ApiResponse(IResultCode resultCode, String msg) {
        this(resultCode,null, msg);
    }

    private ApiResponse(IResultCode resultCode, T data, String msg) {
        this(resultCode.getCode(), data, msg);
    }

    public ApiResponse() {
    }

    private ApiResponse(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
        this.success = ResultCode.SUCCESS.code == code;
    }

    private static <T> ApiResponse<T> createInstance(T data, int code, String msg) {
        ApiResponse<T> apiResponse = new ApiResponse();
        apiResponse.setCode(code);
        apiResponse.setData(data);
        apiResponse.setMsg(msg);
        apiResponse.setSuccess(ResultCode.SUCCESS.code == code);
        return apiResponse;
    }

    private static <T> ApiResponse<T> createInstance(T data, IResultCode resultCode) {
        ApiResponse<T> apiResponse = new ApiResponse();
        apiResponse.setCode(resultCode.getCode());
        apiResponse.setData(data);
        apiResponse.setMsg(resultCode.getMessage());
        apiResponse.setSuccess(ResultCode.SUCCESS.code == resultCode.getCode());
        return apiResponse;
    }

    public static boolean isSuccess(@Nullable ApiResponse<?> result) {
        return (Boolean)Optional.ofNullable(result).map((x) -> {
            return ObjectUtils.nullSafeEquals(ResultCode.SUCCESS.code, x.code);
        }).orElse(Boolean.FALSE);
    }

    public static boolean isNotSuccess(@Nullable ApiResponse<?> result) {
        return !isSuccess(result);
    }

    public static <T> ApiResponse<T> success(T data, String msg) {
        return createInstance(data, ResultCode.SUCCESS.getCode(), msg);
    }

    public static <T> ApiResponse<T> success(T data) {
        return createInstance(data, ResultCode.SUCCESS);
    }

    public static <T> ApiResponse<T> success(int code, T data, String msg) {
        return createInstance(data, code, msg);
    }

    public static <T> ApiResponse<T> success(String msg) {
        return createInstance(null, ResultCode.SUCCESS.getCode(), msg);
    }

    public static <T> ApiResponse<T> success() {
        return createInstance(null, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.message);
    }

    public static <T> ApiResponse<T> success(int code, String msg) {
        return createInstance(null, code, msg);
    }

    public static <T> ApiResponse<T> success(IResultCode resultCode) {
        return createInstance(null, resultCode);
    }

    public static <T> ApiResponse<T> success(IResultCode resultCode, String msg) {
        return createInstance(null, resultCode.getCode(), msg);
    }

    public static <T> ApiResponse<T> fail(String msg) {
        return createInstance(null, ResultCode.FAILURE.getCode(), msg);
    }

    public static <T> ApiResponse<T> fail(int code, T data, String msg) {
        return createInstance(data, code, msg);
    }

    public static <T> ApiResponse<T> fail(int code, String msg) {
        return createInstance(null, code, msg);
    }

    public static <T> ApiResponse<T> fail(IResultCode resultCode) {
        return createInstance(null, resultCode);
    }

    public static <T> ApiResponse<T> fail(IResultCode resultCode, String msg) {
        return createInstance(null, resultCode.getCode(), msg);
    }

    public static <T> ApiResponse<T> status(boolean flag) {
        return flag ? success(ResultCode.SUCCESS.getMessage()) : fail(ResultCode.FAILURE.getMessage());
    }

}
