package jp.sourceforge.nicoro;

import static jp.sourceforge.nicoro.Log.LOG_TAG;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;

import java.io.IOException;

/**
 *
 * AsyncThreadのpoolにしばらくResultのインスタンスが残るらしいため、
 * 弱参照切り替えクラスを使用
 */
public class NicoJSONLoader extends AsyncTaskLoader<ChangeReference<JSONObject>> {
    private final String mHostname;
    private final String mUri;
    private volatile HttpUriRequest mHttpRequest;

    public NicoJSONLoader(Context context, String hostname, String uri) {
        super(context);
        mHostname = hostname;
        mUri = uri;
    }

    @Override
    public ChangeReference<JSONObject> loadInBackground() {
        // TODO ここでCookie取得すべきかどうか
        // 再認証が必要な場合、戻り値のJSONがstatus=fail、errorオブジェクトのcode=NOAUTHになる
        String userSession = NicoroConfig.getCookieUserSession(getContext());

        HttpUriRequest httpRequest = Util.createRequestGetSingleLineDataFromAPI(
                mUri,
                userSession, null);
        mHttpRequest = httpRequest;
        DefaultHttpClient httpClient = Util.createHttpClient();
        JSONObject result = null;
        try {
            httpClient.getCookieStore().clear();
            result = Util.getJSONFromAPI(httpClient,
                    mHostname, httpRequest);
        } catch (ClientProtocolException e) {
            Log.e(LOG_TAG, e.toString(), e);
        } catch (IOException e) {
            if (httpRequest.isAborted()) {
                Log.w(LOG_TAG, e.toString(), e);
            } else {
                Log.e(LOG_TAG, e.toString(), e);
            }
        } catch (JSONException e) {
            Log.e(LOG_TAG, e.toString(), e);
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
        mHttpRequest = null;
        if (result == null) {
            return null;
        } else {
            return new ChangeReference<JSONObject>(result);
        }
    }

    @Override
    protected void onReset() {
        abortHttpRequest();
        mHttpRequest = null;
    }

    @Override
    protected void onStartLoading() {
        forceLoad();
    }

    @Override
    protected void onStopLoading() {
        mHttpRequest = null;
    }

    @Override
    public void onCanceled(ChangeReference<JSONObject> data) {
        if (data != null) {
            data.weaken();
        }
    }

    private void abortHttpRequest() {
        Util.abortHttpUriRequest(mHttpRequest);
    }
}
