/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.common.dto;

import com.crunii.micro.common.exception.ErrorCode;
import com.crunii.micro.common.utils.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.http.HttpStatus;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

/**
 * <pre>
 * 	因为使用泛型的原因才能生成api参数说明
 * </pre>
 *
 * @author 田平 create 2013-4-28上午10:01:02
 */
@Setter
@Getter
@ToString
@ApiModel(description = "基础请求响应结果")
public class Result<T> implements Serializable {

	private static final long serialVersionUID = 1L;
	/**
	 * 默认错误编码
	 */
	public static final String DEFAULT_ERROR_CODE = "-1";
	/**
	 * 默认编码
	 */
	public static final String DEFAULT_CODE = "0";

	@ApiModelProperty(value = "业务调用是否成功")
	private boolean success;

	@ApiModelProperty(value = "错误编码")
	private String code = DEFAULT_CODE;

	@ApiModelProperty(value = "错误信息")
	private String msg;

	/**
	 * 当返回的数据为单对象是实用此属性
	 */
	@ApiModelProperty(value = "业务数据")
	private T data;

	public static <T> Result<T> getResultFromJson(String json, Class<T> dataClass) {

		JavaType javaType = JsonUtil.getMapper().getTypeFactory().constructParametricType(Result.class, dataClass);
		try {
			return JsonUtil.getMapper().readValue(json, javaType);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static <T> Result<T> getResultFromJson(String json, TypeReference<Result<T>> valueTypeRef) {
		try {
			return JsonUtil.getMapper().readValue(json, valueTypeRef);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static <R> Result<R> ofSuccess(R data) {
		Result<R> t = new Result<>();
		t.setMsg("success");
		t.setData(data);
		return t;
	}

	public static Result ofSuccess() {
		Result t = new Result();
		t.setMsg("success");
		return t;
	}

	public static <R> Result<R> ofSuccessWithMsg(R data, String msg) {
		Result<R> t = new Result<>();
		t.setSuccess(true);
		t.setMsg(msg);
		t.setData(data);
		return t;
	}

	public static <R> Result<R> ofFail(ErrorCode errorCode) {
		return ofFail(Integer.toString(errorCode.getCode()), errorCode.getMsg());
	}

	public static <R> Result<R> ofFail(String msg) {
		Result<R> result = new Result<>();
		result.setSuccess(false);
		result.setCode(DEFAULT_ERROR_CODE);
		result.setMsg(msg);
		return result;
	}

	public static <R> Result<R> ofFail(String code,String msg) {
		Result<R> result = new Result<>();
		result.setSuccess(false);
		result.setCode(code);
		result.setMsg(msg);
		return result;
	}

	public static <R> Result<R> ofFail(String code,String msg,R data) {
		Result<R> result = new Result<>();
		result.setSuccess(false);
		result.setCode(code);
		result.setMsg(msg);
		result.setData(data);
		return result;
	}
	public static <R> Result<R> ofFail(String msg,R data) {
		Result<R> result = new Result<>();
		result.setSuccess(false);
		result.setMsg(msg);
		result.setData(data);
		return result;
	}


	public static <R> Result<R> ofSuccessMsg(String msg) {
		Result<R> t = new Result<>();
		t.setMsg(msg);
		return t;
	}

	public static void main(String[] args) {
		Result<List<String>> r = new Result<List<String>>(Arrays.asList("abc", "abc1"));
		System.out.println(getResultFromJson(JsonUtil.getJsonString(r), new TypeReference<Result<List<String>>>() {}));
	}

	public Result() {
		this.success = true;
	}

	public Result(HttpStatus status) {
		this.success = true;
		this.code = String.valueOf(status.value());
		this.msg = status.getReasonPhrase();
	}

	public Result(boolean success) {
		this.success = success;
	}

	public Result(T data) {
		this.success = true;
		this.data = data;
	}

	public Result(boolean success, T data) {
		this.success = success;
		this.data = data;
	}

	public Result(boolean success, String code, T data) {
		this.success = success;
		this.code = code;
		this.data = data;
	}

	public Result(String msg, boolean success) {
		this.msg = msg;
		this.success = success;
	}

	public Result(boolean success, String code, String msg) {
		this.success = success;
		this.code = code;
		this.msg = msg;
	}

	public Result(boolean success, String code, String msg, T data) {
		this.success = success;
		this.code = code;
		this.msg = msg;
		this.data = data;
	}

	public String getCode() {
		return code;
	}

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

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	/**
	 * @return the success
	 */
	public boolean isSuccess() {
		return success;
	}

	/**
	 * @param success the success to set
	 */
	public void setSuccess(boolean success) {
		this.success = success;
	}

	/**
	 * @return the data
	 */
	public T getData() {
		return data;
	}

	/**
	 * @param data the data to set
	 */
	public void setData(T data) {
		this.data = data;
	}
}
