package ru.yandex.webmaster.common.http;

import java.util.Collections;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import org.joda.time.DateTime;

/**
 * <pre><code>
 * {
 *     "application": "webmaster-viewer",
 *     "version": "1.2.3",
 *     "startDate": "2014-01-10T15:23:48+04:00"
 *     "action": "host/limits/getForHost",
 *     "status": "success",
 *     "duration": "128",
 *
 *     "request": {
 *         ...
 *     },
 *
 *     "response": {
 *         ...
 *     },
 *
 *     "errors": [{
 *         "code": "",
 *         "class": "",
 *         "message": "",
 *         "stackTrace": ""
 *     }]
 * }
 * </code></pre>

 * @author aherman
 */
@JacksonXmlRootElement(localName = "response")
public class GenericActionResponse {
    private final String application;
    private final String version;
    private final DateTime startDate;
    private final String action;
    private final ActionStatus status;
    private final long duration;

    private final Object request;
    private final Object data;
    private final ActionError[] errors;

    GenericActionResponse(String application, String version, DateTime startDate, String action,
            ActionStatus status, long duration, Object request, Object response,
            ActionError error)
    {
        this.application = application;
        this.version = version;
        this.startDate = startDate;
        this.action = action;
        this.status = status;
        this.duration = duration;
        this.request = request;
        this.data = response;
        if (error != null) {
            this.errors = new ActionError[]{error};
        } else {
            this.errors = null;
        }
    }

    public String getApplication() {
        return application;
    }

    public String getVersion() {
        return version;
    }

    public DateTime getStartDate() {
        return startDate;
    }

    public String getAction() {
        return action;
    }

    public ActionStatus getStatus() {
        return status;
    }

    public long getDuration() {
        return duration;
    }

    public Object getRequest() {
        return request;
    }

    public Object getData() {
        return data;
    }

    @JacksonXmlElementWrapper(localName = "errors")
    @JacksonXmlProperty(localName = "error")
    public ActionError[] getErrors() {
        return errors;
    }

    public static class ActionError {
        private final Enum<?> code;
        private final Enum<?> subsystem;
        private final String clazz;
        private final String message;
        private final String stackTrace;
        private final Map<String, String> params;

        public ActionError(Enum<?> code, Enum<?> subsystem, String clazz, String message, String stackTrace) {
            this(code, subsystem, clazz, message, stackTrace, Collections.<String, String>emptyMap());
        }

        ActionError(Enum<?> code, Enum<?> subsystem, String clazz, String message, String stackTrace, Map<String, String> params) {
            this.code = code;
            this.subsystem = subsystem;
            this.clazz = clazz;
            this.message = message;
            this.stackTrace = stackTrace;
            this.params = params;
        }

        public Enum<?> getCode() {
            return code;
        }

        public Enum<?> getSubsystem() {
            return subsystem;
        }

        @JsonProperty("class")
        public String getClazz() {
            return clazz;
        }

        public String getMessage() {
            return message;
        }

        public String getStackTrace() {
            return stackTrace;
        }

        public Map<String, String> getParams() {
            return params;
        }
    }
}
