package fr.free.nrw.commons.upload;

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import com.android.volley.Cache;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import com.android.volley.toolbox.Volley;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;


import java.io.UnsupportedEncodingException;
import java.util.HashSet;

public class MwVolleyApi {

    private static RequestQueue REQUEST_QUEUE;
    private static final Gson GSON = new GsonBuilder().create();
    private Context context;

    protected static HashSet<String> categorySet;

    public MwVolleyApi(Context context) {
        this.context = context;
        categorySet = new HashSet<String>();
    }

    public void request(String coords) {

        String apiUrl = buildUrl(coords);
        Log.d("Image", "URL: " + apiUrl);

        JsonRequest<QueryResponse> request = new QueryRequest(apiUrl,
                new LogResponseListener<QueryResponse>(), new LogResponseErrorListener());
        getQueue().add(request);
    }

    /**
     * Builds URL with image coords for MediaWiki API calls
     * Example URL: https://commons.wikimedia.org/w/api.php?action=query&prop=categories|coordinates|pageprops&format=json&clshow=!hidden&coprop=type|name|dim|country|region|globe&codistancefrompoint=38.11386944444445|13.356263888888888&
     * generator=geosearch&redirects=&ggscoord=38.11386944444445|13.356263888888888&ggsradius=100&ggslimit=10&ggsnamespace=6&ggsprop=type|name|dim|country|region|globe&ggsprimary=all&formatversion=2
     */
    private String buildUrl (String coords){

        Uri.Builder builder = Uri.parse("https://commons.wikimedia.org/").buildUpon();

        builder.appendPath("w")
                .appendPath("api.php")
                .appendQueryParameter("action", "query")
                .appendQueryParameter("prop", "categories|coordinates|pageprops")
                .appendQueryParameter("format", "json")
                .appendQueryParameter("clshow", "!hidden")
                .appendQueryParameter("coprop", "type|name|dim|country|region|globe")
                .appendQueryParameter("codistancefrompoint", coords)
                .appendQueryParameter("generator", "geosearch")
                .appendQueryParameter("ggscoord", coords)
                .appendQueryParameter("ggsradius", "100")
                .appendQueryParameter("ggslimit", "10")
                .appendQueryParameter("ggsnamespace", "6")
                .appendQueryParameter("ggsprop", "type|name|dim|country|region|globe")
                .appendQueryParameter("ggsprimary", "all")
                .appendQueryParameter("formatversion", "2");

        return builder.toString();
    }

    private synchronized RequestQueue getQueue() {
        return getQueue(context);
    }

    private static RequestQueue getQueue(Context context) {
        if (REQUEST_QUEUE == null) {
            REQUEST_QUEUE = Volley.newRequestQueue(context.getApplicationContext());
        }
        return REQUEST_QUEUE;
    }

    private static class LogResponseListener<T> implements Response.Listener<T> {
        private static final String TAG = LogResponseListener.class.getName();

        @Override
        public void onResponse(T response) {
            Log.d(TAG, response.toString());
        }
    }

    private static class LogResponseErrorListener implements Response.ErrorListener {
        private static final String TAG = LogResponseErrorListener.class.getName();

        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e(TAG, error.toString());
        }
    }

    private static class QueryRequest extends JsonRequest<QueryResponse> {
        private static final String TAG = QueryRequest.class.getName();

        public QueryRequest(String url,
                            Response.Listener<QueryResponse> listener,
                            Response.ErrorListener errorListener) {
            super(Request.Method.GET, url, null, listener, errorListener);
        }

        @Override
        protected Response<QueryResponse> parseNetworkResponse(NetworkResponse response) {
            String json = parseString(response);
            //Log.d(TAG, "json=" + json);
            QueryResponse queryResponse = GSON.fromJson(json, QueryResponse.class);
            return Response.success(queryResponse, cacheEntry(response));
        }

        private Cache.Entry cacheEntry(NetworkResponse response) {
            return HttpHeaderParser.parseCacheHeaders(response);
        }

        private String parseString(NetworkResponse response) {
            try {
                return new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            } catch (UnsupportedEncodingException e) {
                return new String(response.data);
            }
        }
    }

    private static class QueryResponse {
        private Query query = new Query();
        private Page page;

        private String printSet() {
            if (categorySet == null || categorySet.isEmpty()) {
                return "No collection of categories";
            }
            else {

                return "CATEGORIES FOUND" + categorySet.toString();
            }
        }
        @Override
        public String toString() {
            return "query=" + query.toString() + "\n" + printSet();
        }
    }

    private static class Query {
        private Page [] pages;

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder("pages=" + "\n");
            for (Page page : pages) {
                builder.append(page.toString());
                builder.append("\n");
            }
            builder.replace(builder.length() - 1, builder.length(), "");

            return builder.toString();

        }
    }

    private static class Page {
        private int pageid;
        private int ns;
        private String title;
        private Category[] categories;
        private Category category;

        @Override
        public String toString() {

            StringBuilder builder = new StringBuilder("PAGEID=" + pageid + " ns=" + ns + " title=" + title + "\n" + " CATEGORIES= ");

            if (categories == null || categories.length == 0) {
                builder.append("no categories exist\n");
            }
            else {
                for (Category category : categories) {
                    builder.append(category.toString());
                    builder.append("\n");
                    if (category != null) {
                        String categoryString = category.toString().replace("Category:", "");
                        categorySet.add(categoryString);
                        //Log.d("Set", "category added: " + category.toString());
                        //Log.d("Set", "Current category Set" + categorySet.toString());
                    }
                }
            }

            builder.replace(builder.length() - 1, builder.length(), "");
            return builder.toString();
        }
    }

        private static class Category {
            private String title;

            @Override
            public String toString() {
                return title;
            }
        }
    }




@@ -609,22 +609,73 @@
 va.util.
-HashSe
+ArrayList;%0Aimport java.util.HashSet;%0Aimport java.util.Lis
 t;%0A%0Apubl
@@ -1013,24 +1013,220 @@
 %3E();%0A    %7D%0A%0A
+    //To get the list of categories for display%0A    public ArrayList%3CString%3E getCategoriesGps() %7B%0A        ArrayList%3CString%3E list = new ArrayList%3CString%3E(categorySet);%0A        return list;%0A    %7D%0A%0A%0A
     public v

Put in basic accessor method for categories