package com.dtflys.forest.reflection;

import com.dtflys.forest.callback.OnProgress;
import com.dtflys.forest.callback.OnSuccess;
import com.dtflys.forest.exceptions.ForestNetworkException;
import com.dtflys.forest.exceptions.ForestRuntimeException;
import com.dtflys.forest.handler.LifeCycleHandler;
import com.dtflys.forest.handler.ResultHandler;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.utils.ForestProgress;
import com.dtflys.forest.utils.ReflectUtil;

import java.lang.reflect.Type;

/**
 * @author gongjun[jun.gong@thebeastshop.com]
 * @since 2017-05-19 17:00
 */
public class MethodLifeCycleHandler<T> implements LifeCycleHandler {

    private final Type returnType;

    private final Class returnClass;

    private final Type onSuccessClassGenericType;

    private static final ResultHandler resultHandler = new ResultHandler();

    private volatile T resultData;

    public MethodLifeCycleHandler(ForestMethod method, Type onSuccessClassGenericType) {
        this.onSuccessClassGenericType = onSuccessClassGenericType;
        this.returnType = method.getReturnType();
        this.returnClass = method.getReturnClass();
    }

    @Override
    public Object handleSync(ForestRequest request, ForestResponse response) {
        return handleSyncWitchException(request, response, null);
    }

    @Override
    public Object handleSyncWitchException(ForestRequest request, ForestResponse response, Exception ex) {
        try {
            Object resultData = handleResultType(request, response, returnType, returnClass);
            if (resultData instanceof ForestResponse) {
                handleResult(resultData);
                return resultData;
            }
            if (response.isSuccess()) {
                resultData = handleSuccess(resultData, request, response);
            } else {
                if (ex != null) {
                    handleError(request, response, ex);
                }
                else {
                    handleError(request, response);
                }
            }
            handleResult(resultData);
            return resultData;
        } catch (Throwable e) {
            throw e;
        } finally {
            request.getInterceptorChain().afterExecute(request, response);
        }
    }

    @Override
    public Object handleResultType(ForestRequest request, ForestResponse response) {
        return handleResultType(request, response, returnType, returnClass);
    }


    @Override
    public synchronized Object handleResultType(ForestRequest request, ForestResponse response, Type resultType, Class resultClass) {
        Object resultData = resultHandler.getResult(request, response, resultType, resultClass);
        if (!(resultData instanceof ForestResponse)) {
            response.setResult(resultData);
        }
        this.resultData = (T) resultData;
        return resultData;
    }

    @Override
    public Object handleSuccess(Object resultData, ForestRequest request, ForestResponse response) {
        request.getInterceptorChain().onSuccess(resultData, request, response);
        OnSuccess onSuccess = request.getOnSuccess();
        if (onSuccess != null) {
            resultData = resultHandler.getResult(request, response, onSuccessClassGenericType, ReflectUtil.getClassByType(onSuccessClassGenericType));
            onSuccess.onSuccess(resultData, request, response);
        }
        resultData = response.getResult();
        return resultData;
    }

    @Override
    public void handleError(ForestRequest request, ForestResponse response) {
        ForestNetworkException networkException = new ForestNetworkException("", response.getStatusCode(), response);
        handleError(request, response, networkException);
    }

    @Override
    public void handleError(ForestRequest request, ForestResponse response, Exception ex) {
        ForestRuntimeException e = null;
        if (ex instanceof ForestRuntimeException) {
            e = (ForestRuntimeException) ex;
        }
        else {
            e = new ForestRuntimeException(ex);
        }
        request.getInterceptorChain().onError(e, request, response);
        if (request.getOnError() != null) {
            request.getOnError().onError(e, request, response);
        }
        else {
            throw e;
        }
    }

    @Override
    public void handleProgress(ForestRequest request, ForestProgress progress) {
//        request.getInterceptorChain().onProgress(progress);
        OnProgress onProgress = request.getOnProgress();
        if (onProgress != null) {
            onProgress.onProgress(progress);
        }
    }

    @Override
    public Object handleResult(Object resultData) {
        this.resultData = (T) resultData;
        return resultData;
    }


    @Override
    public Type getReturnType() {
        return returnType;
    }

    public T getResultData() {
        return resultData;
    }

    @Override
    public Type getOnSuccessClassGenericType() {
        return onSuccessClassGenericType;
    }
}

@@ -522,16 +522,17 @@
 lectUtil
+s
 ;%0A%0Aimpor
@@ -562,16 +562,31 @@
 e;%0A%0A/**%0A
+ * %E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%A4%84%E7%90%86%E5%99%A8%0A
  * @auth
@@ -2961,32 +2961,34 @@
 ultData;%0A    %7D%0A%0A
+%0A%0A
     @Override%0A  
@@ -3359,16 +3359,17 @@
 lectUtil
+s
 .getClas
@@ -3548,32 +3548,226 @@
 ultData;%0A    %7D%0A%0A
+    @Override%0A    public void handleInvokeMethod(ForestRequest request, ForestMethod method, Object%5B%5D args) %7B%0A        request.getInterceptorChain().onInvokeMethod(request, method, args);%0A    %7D%0A%0A
     @Override%0A  

生命周期方法 handleInvokeMethod