// Path: sdk/src/main/java/com/theeyetribe/clientsdk/request/Request.java
// public class Request<T> implements Comparable<Request<T>>
// {
//     public String category;
//     public String request;
//     public int id;
// 
//     private transient boolean mCanceled;
// 
//     public transient long timeStamp;
// 
//     public transient int retryAttempts;
// 
//     public transient Object asyncLock;
// 
//     private transient final Class<T> type;
// 
//     public Request(Class<T> type) {
//         this.type = type;
//     }
// 
//     public T parseJsonResponse(JsonObject response, Gson gson)
//     {
//         if(GazeManager.IS_DEBUG_MODE)
//             System.out.println("parseJsonResponse: " + type.getSimpleName());
// 
//         return gson.fromJson(response, type);
//     }
// 
//     public String toJsonString(Gson gson)
//     {
//         if(GazeManager.IS_DEBUG_MODE)
//             System.out.println("toJsonString: " + this.getClass().getSimpleName());
// 
//         return gson.toJson(this, this.getClass());
//     }
// 
//     public void cancel()
//     {
//         mCanceled = true;
//         finish();
//     }
// 
//     public boolean isCancelled()
//     {
//         return mCanceled;
//     }
// 
//     public void finish()
//     {
//         if(null != asyncLock)
//         {
//             synchronized (asyncLock)
//             {
//                 asyncLock.notify();
//             }
//         }
//     }
// 
//     @Override
//     public boolean equals(Object o)
//     {
//         if (this == o)
//             return true;
// 
//         if (!(o instanceof Request))
//             return false;
// 
//         Request other = (Request) o;
// 
//         return category.equals(other.category) &&
//                 request.equals(other.request) &&
//                 id == other.id;
//     }
// 
//     @Override
//     public int hashCode()
//     {
//         int hash = 1471;
//         hash = hash * 1151  + category.hashCode();
//         hash = hash * 1151  + request.hashCode();
//         hash = hash * 1151  + HashUtils.hash(id);
//         return hash;
//     }
// 
//     @Override
//     public int compareTo(Request other)
//     {
//         if(this.equals(other))
//             return 0;
// 
//         if(this.id != 0 && other.id == 0)
//             return -1;
// 
//         if(this.id == 0 && other.id != 0)
//             return 1;
// 
//         //if(this.id != 0 && other.id != 0)
//             return this.id < other.id ? -1 : 1;
//     }
// }
// 
// Path: sdk/src/main/java/com/theeyetribe/clientsdk/response/Response.java
// public class Response
// {
//     public String category;
//     public String request;
//     public int id;
//     public int statuscode;
// 
//     public transient long transitTime;
// }


import com.theeyetribe.clientsdk.data.GazeData;
import com.theeyetribe.clientsdk.request.Request;
import com.theeyetribe.clientsdk.response.Response;
/*
 * Copyright (c) 2013-present, The Eye Tribe.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree.
 *
 */
package com.theeyetribe.clientsdk;


/**
 * GazeManager is the main entry point of the EyeTribe Java SDK. It exposes all routines associated to gaze control.
 * <p>
 * Using this class a developer can connect to the EyeTribe Server, <i>calibrate</i> the eye tracking system and attach
 * listeners to receive live data streams of {@link GazeData} updates. Note that this is a thin wrapper class. The Core
 * SDK implementation can be found in {@link GazeManagerCore}.
 * <p>
 * GazeManager must establish a connection to the EyeTribe Server before it can be used. This is achieved by calling
 * {@link #activate() activate}. GazeManager must be shut down by calling {@link #deactivate() deactivate}.
 * <p>
 * A standard pattern for using GazeManager in a Java FX Application can be seen below:
 * <pre>
 * public class Main extends Application{
 *
 *     public static void main(String[] args)
 *     {
 *         launch(args);
 *     }
 *
 *     \@Override
 *     public void start(Stage primaryStage) throws Exception
 *     {
 *         GazeManager.getInstance().activateAsync();
 *     }
 *
 *     \@Override
 *     public void stop() throws Exception
 *     {
 *         GazeManager.getInstance().deactivate();
 *     }
 * }
 * </pre>
 */
public class GazeManager extends GazeManagerCore
{
    private GazeManager()
    {
        super();
    }

    public static GazeManager getInstance()
    {
        return Holder.INSTANCE;
    }

    private static class Holder
    {
        // thread-safe initialization on demand
        static final GazeManager INSTANCE = new GazeManager();
    }

    protected GazeApiManager createApiManager(GazeApiManager.IGazeApiResponseListener responseListener, GazeApiManager.IGazeApiConnectionListener connectionListener)
    {
        return new GazeApiManager(responseListener, connectionListener);
    }

// Path: sdk/src/main/java/com/theeyetribe/clientsdk/request/Request.java
// public class Request<T> implements Comparable<Request<T>>
// {
//     public String category;
//     public String request;
//     public int id;
// 
//     private transient boolean mCanceled;
// 
//     public transient long timeStamp;
// 
//     public transient int retryAttempts;
// 
//     public transient Object asyncLock;
// 
//     private transient final Class<T> type;
// 
//     public Request(Class<T> type) {
//         this.type = type;
//     }
// 
//     public T parseJsonResponse(JsonObject response, Gson gson)
//     {
//         if(GazeManager.IS_DEBUG_MODE)
//             System.out.println("parseJsonResponse: " + type.getSimpleName());
// 
//         return gson.fromJson(response, type);
//     }
// 
//     public String toJsonString(Gson gson)
//     {
//         if(GazeManager.IS_DEBUG_MODE)
//             System.out.println("toJsonString: " + this.getClass().getSimpleName());
// 
//         return gson.toJson(this, this.getClass());
//     }
// 
//     public void cancel()
//     {
//         mCanceled = true;
//         finish();
//     }
// 
//     public boolean isCancelled()
//     {
//         return mCanceled;
//     }
// 
//     public void finish()
//     {
//         if(null != asyncLock)
//         {
//             synchronized (asyncLock)
//             {
//                 asyncLock.notify();
//             }
//         }
//     }
// 
//     @Override
//     public boolean equals(Object o)
//     {
//         if (this == o)
//             return true;
// 
//         if (!(o instanceof Request))
//             return false;
// 
//         Request other = (Request) o;
// 
//         return category.equals(other.category) &&
//                 request.equals(other.request) &&
//                 id == other.id;
//     }
// 
//     @Override
//     public int hashCode()
//     {
//         int hash = 1471;
//         hash = hash * 1151  + category.hashCode();
//         hash = hash * 1151  + request.hashCode();
//         hash = hash * 1151  + HashUtils.hash(id);
//         return hash;
//     }
// 
//     @Override
//     public int compareTo(Request other)
//     {
//         if(this.equals(other))
//             return 0;
// 
//         if(this.id != 0 && other.id == 0)
//             return -1;
// 
//         if(this.id == 0 && other.id != 0)
//             return 1;
// 
//         //if(this.id != 0 && other.id != 0)
//             return this.id < other.id ? -1 : 1;
//     }
// }
// 
// Path: sdk/src/main/java/com/theeyetribe/clientsdk/response/Response.java
// public class Response
// {
//     public String category;
//     public String request;
//     public int id;
//     public int statuscode;
// 
//     public transient long transitTime;
// }


// Path: sdk/src/main/java/com/theeyetribe/clientsdk/GazeManager.java
import com.theeyetribe.clientsdk.data.GazeData;
import com.theeyetribe.clientsdk.request.Request;
import com.theeyetribe.clientsdk.response.Response;

/*
 * Copyright (c) 2013-present, The Eye Tribe.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree.
 *
 */
package com.theeyetribe.clientsdk;


/**
 * GazeManager is the main entry point of the EyeTribe Java SDK. It exposes all routines associated to gaze control.
 * <p>
 * Using this class a developer can connect to the EyeTribe Server, <i>calibrate</i> the eye tracking system and attach
 * listeners to receive live data streams of {@link GazeData} updates. Note that this is a thin wrapper class. The Core
 * SDK implementation can be found in {@link GazeManagerCore}.
 * <p>
 * GazeManager must establish a connection to the EyeTribe Server before it can be used. This is achieved by calling
 * {@link #activate() activate}. GazeManager must be shut down by calling {@link #deactivate() deactivate}.
 * <p>
 * A standard pattern for using GazeManager in a Java FX Application can be seen below:
 * <pre>
 * public class Main extends Application{
 *
 *     public static void main(String[] args)
 *     {
 *         launch(args);
 *     }
 *
 *     \@Override
 *     public void start(Stage primaryStage) throws Exception
 *     {
 *         GazeManager.getInstance().activateAsync();
 *     }
 *
 *     \@Override
 *     public void stop() throws Exception
 *     {
 *         GazeManager.getInstance().deactivate();
 *     }
 * }
 * </pre>
 */
public class GazeManager extends GazeManagerCore
{
    private GazeManager()
    {
        super();
    }

    public static GazeManager getInstance()
    {
        return Holder.INSTANCE;
    }

    private static class Holder
    {
        // thread-safe initialization on demand
        static final GazeManager INSTANCE = new GazeManager();
    }

    protected GazeApiManager createApiManager(GazeApiManager.IGazeApiResponseListener responseListener, GazeApiManager.IGazeApiConnectionListener connectionListener)
    {
        return new GazeApiManager(responseListener, connectionListener);
    }

    protected boolean parseApiResponse(final Response response, final Request request)