package cz.muni.ics.oidc.saml;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.util.StringUtils;

@Getter
public class ExtendedOAuth2Exception extends OAuth2Exception {

    public static final String ERROR_UNMET_AUTHENTICATION_REQUIREMENTS = "unmet_authentication_requirements";
    public static final String ERROR_LOGIN_REQUIRED = "login_required";

    public static final String KEY_ERROR_CODE = "errorCode";
    public static final String KEY_ERROR_DESCRIPTION = "errorDescription";

    public static final String KEY_REDIRECT_URI = "redirectUri";
    public static final String KEY_STATE = "state";

    private final String errorCode;

    private final String redirectUri;

    private final String state;

    public ExtendedOAuth2Exception(String errorCode, String msg) {
        this(errorCode, msg, null, null);
    }

    public ExtendedOAuth2Exception(String errorCode, String msg, String redirectUri, String state) {
        super(msg);
        this.errorCode = errorCode;
        this.redirectUri = redirectUri;
        this.state = state;
    }

    @Override
    public int getHttpErrorCode() {
        if (ERROR_UNMET_AUTHENTICATION_REQUIREMENTS.equals(this.errorCode)) {
            return HttpStatus.FORBIDDEN.value();
        }
        return super.getHttpErrorCode();
    }

    public static ExtendedOAuth2Exception deserialize(String strJson) {
        if (!StringUtils.hasText(strJson)) {
            return null;
        }
        JsonObject json = (JsonObject) JsonParser.parseString(strJson);
        String errorCode = json.get(KEY_ERROR_CODE).isJsonNull() ? null : json.get(KEY_ERROR_CODE).getAsString();
        String errorMessage = json.get(KEY_ERROR_DESCRIPTION).isJsonNull() ? null : json.get(KEY_ERROR_DESCRIPTION).getAsString();
        String redirectUri = json.get(KEY_REDIRECT_URI).isJsonNull() ? null : json.get(KEY_REDIRECT_URI).getAsString();
        String state = json.get(KEY_STATE).isJsonNull() ? null : json.get(KEY_STATE).getAsString();
        return new ExtendedOAuth2Exception(errorCode, errorMessage, redirectUri, state);
    }

    public static String serialize(ExtendedOAuth2Exception o) {
        if (o == null) {
            return null;
        }
        JsonObject object = new JsonObject();
        object.addProperty(KEY_ERROR_CODE, o.getOAuth2ErrorCode());
        object.addProperty(KEY_ERROR_DESCRIPTION, o.getMessage());
        object.addProperty(KEY_REDIRECT_URI, o.getRedirectUri());
        object.addProperty(KEY_STATE, o.getState());
        return object.toString();
    }

    @Override
    public String getOAuth2ErrorCode() {
        return errorCode;
    }

}
