package me.chyxion.tigon.webmvc;

import lombok.Getter;
import java.util.Map;
import java.util.HashMap;

/**
 * @author Shaun Chyxion <br>
 * chyxion@163.com <br>
 * Sep 21, 2014 8:32:06 PM
 */
public class JSONViewDataModel {

    @Getter
    private boolean success = true;
    /**
     * error code
     */
    @Getter
    private Object code = 0;
    @Getter
    private Object message;
    @Getter
    private Object data;
    @Getter
    private Map<String, Object> attrs;
    @Getter
    private Throwable exception;

    /**
     * @since 0.0.3
     */
    public JSONViewDataModel() {
    }

    /**
     * @param data
     */
    public JSONViewDataModel(Object data) {
        this.data = data;
    }

    /**
     * @since 0.0.3
     * @param exception
     */
    public JSONViewDataModel(Throwable exception) {
        this.exception = exception;
    }

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

    /**
     * @param code the code to set
     * @return 
     */
    public JSONViewDataModel setCode(Object code) {
        this.code = code;
        return this;
    }

    /**
     * @param message the message to set
     * @return this
     */
    public JSONViewDataModel setMessage(Object message) {
        this.message = message;
        return this;
    }

    /**
     * @param data the data to set
     */
    public JSONViewDataModel setData(Object data) {
        this.data = data;
        return this;
    }

    /**
     * @return formatted data map
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> toMap(
        final String successKey,
        final String dataKey,
        final String codeKey,
        final String messageKey) {

        final Map<String, Object> mapData = new HashMap<>();
        if (attrs != null) {
            mapData.putAll(attrs);
        }
        if (data != null) {
            mapData.put(dataKey, data);
        }
        mapData.put(successKey, success);
        mapData.put(codeKey, code);
        if (!success) {
            mapData.put(messageKey, getMessageOrExceptionMessage());
        }
        return mapData;
    }

    /**
     * @param exception the exception to set
     */
    public void setException(Throwable exception) {
        this.exception = exception;
    }

    /**
     * @param attrs the attrs to set
     * @return this
     */
    public JSONViewDataModel setAttrs(Map<String, Object> attrs) {
        this.attrs = attrs;
        return this;
    }
    
    /**
     * set attr
     * @param name attr name
     * @param value attr value
     * @return this
     */
    public JSONViewDataModel setAttr(String name, Object value) {
        if (attrs == null) {
            attrs = new HashMap<String, Object>();
        }
        attrs.put(name, value);
        return this;
    }

    /**
     * get attr
     * @param name attr name
     * @return attr value
     */
    @SuppressWarnings("unchecked")
    public <T> T getAttr(String name) {
        return attrs != null ? (T) attrs.get(name) : null;
    }

    /**
     * get attr
     * @param name attr name
     * @return attr value
     */
    @SuppressWarnings("unchecked")
    public <T> T removeAttr(String name) {
        return attrs != null ? (T) attrs.remove(name) : null;
    }

    /**
     * @return the message
     */
    protected Object getMessageOrExceptionMessage() {
        return message != null ? message : 
            exception != null ? exception.getMessage() : null;
    }
}
