package com.liquidnet.service;

import com.alibaba.fastjson.JSON;
import com.liquidnet.service.constant.GlobalConstant;
import com.liquidnet.common.exception.constant.ErrorCode;
import com.liquidnet.common.exception.constant.ServiceErrorCode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * REDIRECT(-1),
 * SUCCESS(0),
 * FAIL(1),
 * UNAUTH(2),
 */
@ApiModel()
public class ResponseDto<T> implements Serializable {
    private static final long serialVersionUID = 1585289779755226637L;

    @ApiModelProperty(value = "错误码,0代表成功",position = -9998)
    private String code;
    @ApiModelProperty(value = "错误描述",position = -9997)
    private String message;
    @ApiModelProperty
    private T data;

    public boolean isSuccess() {
        return this.code.equals(ErrorCode.SUCCESS.getCode());
    }

    public ResponseDto() {
    }

    public ResponseDto(String code) {
        this.code = code;
    }

    public ResponseDto(String code, T data) {
        this.code = code;
        this.data = data;
    }

    public ResponseDto(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public ResponseDto(String code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public ResponseDto(ErrorCode errorCode) {
        this.code = errorCode.getCode();
        this.message = errorCode.getMessage();
    }

    public static<Object> ResponseDto<Object> success(Object data) {
        return new ResponseDto<>(ErrorCode.SUCCESS.getCode(), data);
    }

    public static<Object> ResponseDto<Object> success() {
        return new ResponseDto<>(ErrorCode.SUCCESS.getCode());
    }

    public static Builder newSuccessBuilder() {
        return new Builder(ErrorCode.SUCCESS);
    }

    public static<Object> ResponseDto<Object> failure(String code, String message) {
        return new ResponseDto<>(code, message);
    }

    public static<Object> ResponseDto<Object> failure(String code, String message, Object data) {
        return new ResponseDto<>(code, message, data);
    }

    public static<Object> ResponseDto<Object> failure(String message) {
        return new ResponseDto<>("1", message);
    }

    public static<Object> ResponseDto<Object> failure(ErrorCode errorCode) {
        return new ResponseDto<>(errorCode);
    }


    /**
     * 自定义异常信息
     *
     * @param errorCode
     * @param message
     * @return ResponseDto<?>
     */
    public static<Object> ResponseDto<Object> failure(ServiceErrorCode errorCode, String message) {
        return new ResponseDto<>(errorCode.getCode(), message);
    }

    public static<Object> ResponseDto<Object> failure(ServiceErrorCode errorCode, Object data) {
        return new ResponseDto<>(errorCode.getCode(), errorCode.getMessage(), data);
    }

    public static<Object> ResponseDto<Object> failure(ServiceErrorCode errorCode) {
        return new ResponseDto<>(errorCode.getCode(), errorCode.getMessage());
    }

    public static<Object> ResponseDto<Object> failure() {
        return new ResponseDto<>(ErrorCode.ERROR.getCode(), ErrorCode.RESPONSE_ERROE_UNKNOWN.getMessage());
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    /**
     * <p>Getter for the field <code>data</code>.</p>
     *
     * @return a T object.
     */
    public T getData() {
        return data;
    }

    /**
     * <p>Setter for the field <code>data</code>.</p>
     *
     * @param data a T object.
     */
    public void setData(T data) {
        this.data = data;
    }

    public <T> T getParseData(Class<T> clazz) {
        try {
            if (getData() != null) {
                return JSON.parseObject(JSON.toJSONString(getData()), clazz);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * <p>redirect.</p>
     *
     * @param path a {@link java.lang.String} object.
     * @return a {@link ResponseDto} object.
     */
    public static ResponseDto<Map<String, Object>> redirect(String path) {
        return new Builder(ErrorCode.REDIRECT).put("url", path).build();
    }

    public static class Builder {
        private final ResponseDto<Map<String, Object>> responseDto;

        private final String code;
        private final Map<String, Object> mapData;

        public Builder(ErrorCode errorCode) {
            responseDto = new ResponseDto<>();

            this.code = errorCode.getCode();
            this.mapData = new HashMap<>();
        }

        public Builder put(String key, Object value) {
            mapData.put(key, value);
            return this;
        }

        public ResponseDto<Map<String, Object>> build() {
            responseDto.setCode(this.code);
            responseDto.setData(this.mapData);
            return responseDto;
        }
    }
}
