package com.lyndir.lhunath.opal.json;

import com.google.gson.Gson;
import com.google.gson.annotations.Expose;
import com.lyndir.lhunath.opal.system.util.MetaObject;
import com.lyndir.lhunath.opal.system.util.ObjectUtils;
import java.io.Serializable;


/**
 * A wrapper for sending {@link Gson} serializable data via a webservice and provide success/failure context data.  Works well with the
 * iLibs webservice classes.
 *
 * <p> <i>11 22, 2010</i> </p>
 *
 * @author lhunath
 */
public class JSONResult extends MetaObject {

    public static final int CODE_SUCCESS                 = 0;
    public static final int CODE_FAILURE_GENERIC         = -1;
    public static final int CODE_FAILURE_UPDATE_REQUIRED = -2;

    public static final String REQUEST_KEY_VERSION = "version";

    @Expose
    private final int      code;
    @Expose
    private final String   userDescription;
    @Expose
    private final String[] userDescriptionArguments;
    @Expose
    private final String   technicalDescription;
    @Expose
    private       boolean  outdated;

    @Expose
    private final Object result;

    private JSONResult(final Object result, final int code, final String technicalDescription, final String userDescription,
                       final Object... userDescriptionArguments) {

        this.result = result;
        this.code = code;
        this.technicalDescription = technicalDescription;
        this.userDescription = userDescription;
        if (this.userDescription == null)
            this.userDescriptionArguments = null;
        else {
            this.userDescriptionArguments = new String[userDescriptionArguments.length];
            for (int o = 0; o < userDescriptionArguments.length; ++o)
                this.userDescriptionArguments[o] = ObjectUtils.ifNotNullElse( userDescriptionArguments[o], "" ).toString();
        }
    }

    public static JSONResult success(final Object result) {

        return new JSONResult( result, CODE_SUCCESS, null, null );
    }

    public static JSONResult failureUpdateRequired(Serializable requiredVersion) {

        return new JSONResult( null, CODE_FAILURE_UPDATE_REQUIRED, "The server does not work with clients older than " + requiredVersion,
                               "server.error.outdated", requiredVersion ).setOutdated( true );
    }

    public static JSONResult failure(final String technicalDescription, final String userDescription,
                                     final Object... userDescriptionArguments) {

        return new JSONResult( null, CODE_FAILURE_GENERIC, technicalDescription, userDescription, userDescriptionArguments );
    }

    public static JSONResult failure(final int code, final String technicalDescription, final String userDescription,
                                     final Object... userDescriptionArguments) {

        return new JSONResult( null, code, technicalDescription, userDescription, userDescriptionArguments );
    }

    public boolean isOutdated() {

        return outdated;
    }

    public JSONResult setOutdated(final boolean outdated) {

        this.outdated = outdated;

        return this;
    }

    public String getUserDescription() {

        return userDescription;
    }

    public String[] getUserDescriptionArguments() {

        return userDescriptionArguments;
    }

    public String getTechnicalDescription() {

        return technicalDescription;
    }

    public Object getResult() {

        return result;
    }

    public int getCode() {

        return code;
    }
}

@@ -244,16 +244,59 @@
 izable;%0A
+import org.jetbrains.annotations.Nullable;%0A
 %0A%0A/**%0A *
@@ -436,13 +436,13 @@
 %0A * 
-iLibs
+Pearl
  web
@@ -867,32 +867,81 @@
 de;%0A    @Expose%0A
+    private       boolean  outdated;%0A    @Expose%0A
     private fina
@@ -1097,57 +1097,8 @@
 ion;
-%0A    @Expose%0A    private       boolean  outdated;
 %0A%0A  
@@ -1128,24 +1128,26 @@
 inal Object 
+  
 result;%0A%0A   
@@ -1944,24 +1944,34 @@
 ccess(final 
+@Nullable 
 Object resul
@@ -2573,37 +2573,24 @@
  return 
-new JSONResult( null,
+failure(
  CODE_FA
@@ -2893,36 +2893,379 @@
  return 
-new JSONResult( null
+failure( code, null, technicalDescription, userDescription, userDescriptionArguments );%0A    %7D%0A%0A    public static JSONResult failure(final int code, @Nullable final Object result, final String technicalDescription, final String userDescription,%0A                                     final Object... userDescriptionArguments) %7B%0A%0A        return new JSONResult( result
 , code, 
@@ -3330,32 +3330,88 @@
 ments );%0A    %7D%0A%0A
+    public int getCode() %7B%0A%0A        return code;%0A    %7D%0A%0A
     public boole
@@ -3923,63 +3923,7 @@
    %7D
-%0A%0A    public int getCode() %7B%0A%0A        return code;%0A    %7D
 %0A%7D%0A

Allow results with failure JSONResults.