package o2mc.io.dimmldependency.Datastreams;

import android.app.Application;
import android.os.AsyncTask;
import android.util.Log;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * Created by nickyromeijn on 12/02/16.
 * This class pulls the settings object through the use of a DIMML endpoint (which contains a REST API)
 * It parses the configuration object and assigns it to the datastreamsHandler class
 */
public class DatastreamsConfiguration extends AsyncTask<Void, Void, String> {

    private String clientID;
    private String clientSecret;
    private String conf;
    private DatastreamsHandler datastreamsHandler;
    private HashMap trackerMap;
    private DatastreamsSettings settings;
    private DatastreamsConfigurationListener mListener = null;
    private Exception mError = null;
    private Application context = null;

    public DatastreamsConfiguration(String clientID, String clientSecret, DatastreamsHandler datastreamsHandler, Application context) {
        this.clientID = clientID;
        this.clientSecret = clientSecret;
        this.datastreamsHandler = datastreamsHandler;
        this.context = context;
        settings = new DatastreamsSettings();
    }

    public DatastreamsConfiguration setListener(DatastreamsConfigurationListener listener) {
        this.mListener = listener;
        return this;
    }

    /**
     * Parse configuration JSON Object and generate Trackerlist.
     * Trackerlist contains of a list of views that need to be tracked under certain circumstances.
     * @param json
     * @return
     */
    private HashMap jsonDecode(String json) {
        HashMap<String, HashMap<String, ArrayList<TrackingData>>> hmap = new HashMap<>();
        try {
            JSONObject obj = new JSONObject(json);
            settings.set(obj.getJSONObject("settings"));
            JSONArray arr = obj.getJSONArray("trackers");
            for (int i = 0; i < arr.length(); i++) {

                JSONObject trackerJson = arr.getJSONObject(i);
                String activity = trackerJson.getString("activity");
                settings.setDatastreamsActivitySettings(activity, trackerJson.getJSONObject("settings"));

                if (hmap.get(activity) == null) {
                    hmap.put(activity, new HashMap<String, ArrayList<TrackingData>>());
                }

                JSONArray trackers = trackerJson.getJSONArray("track");
                for (int b = 0; b < trackers.length(); b++) {
                    JSONObject tracker = trackers.getJSONObject(b);
                    String trackOnTheseTypes = tracker.getString("type");
//                    for (int c = 0; c < trackOnTheseTypes.length(); c++) {
                    ArrayList<TrackingData> chainLinks = new ArrayList<>();
                    try {
                        JSONArray cLinks = tracker.getJSONArray("chainLinks");
                        if (cLinks.length() > 0) {
                            for (int c = 0; c < cLinks.length(); c++) {
                                JSONObject clinkobj = cLinks.getJSONObject(c);
                                chainLinks.add(new TrackingData("", clinkobj.getString("id"), "", "", clinkobj.getInt("indexWithinActivity")));
                            }
                        }
                    } catch (Exception e) {
//                        Log.e("JSON parse error", "Chainlinks: " + e.toString());
                    }
                    TrackingData tobj = new TrackingData(trackOnTheseTypes, tracker.getString("id"), tracker.getString("tag"), tracker.getString("alias"), tracker.getInt("indexWithinActivity"));
                    tobj.setChainLinks(chainLinks);
                    String trackType = trackOnTheseTypes;
                    ArrayList<TrackingData> trackTypes = hmap.get(activity).get(trackType);

                    if (trackTypes == null) {
                        trackTypes = new ArrayList<TrackingData>();
                        trackTypes.add(tobj);
                        hmap.get(activity).put(trackType, trackTypes);
                    } else {
                        if (!trackTypes.contains(tobj)) trackTypes.add(tobj);
                    }
//                    }
                }

            }
        } catch (JSONException e) {
            e.printStackTrace();
//            mError = e;
        }
        return hmap;
    }


    @Override
    protected String doInBackground(Void... params) {

        BufferedReader in = null;
        String data = null;
        String result = "";
        String pName = Datastream.getApplicationKey();

        /**
         * This crashes on tims phone; why? no clue
         * needs debugging
         */

//        if(context != null) {
//            pName = context.getPackageName();
//        }

        try {
            String requestUrl = "http://dynamic.dimml.io/?dimml.concept=//nromeijn@datastreams.configstore/API&appid=" + Datastream.getApplicationKey();
            HttpClient httpclient = new DefaultHttpClient();
            HttpGet request = new HttpGet(new URI(requestUrl));
            request.setHeader("Content-Type", "application/json");
            HttpResponse response = httpclient.execute(request);

            Log.e("GETTING DATA", requestUrl);
            Log.e("STATUS ", "Status line : " + response.getStatusLine().toString());

            InputStream stream = response.getEntity().getContent();
            in = new BufferedReader(new InputStreamReader(stream));

            String line;
            while ((line = in.readLine()) != null) {
                result = result + line;
            }

        } catch (Exception e) {
            Log.e("log_tag", "Error in http connection " + e.toString());
            mError = e;
        }

        return result;
    }

    @Override
    protected void onPostExecute(String result) {
        this.conf = result;
        trackerMap = jsonDecode(result);
        datastreamsHandler.callback(trackerMap);
        if (this.mListener != null) this.mListener.onComplete(result, mError, trackerMap);
    }

    public static interface DatastreamsConfigurationListener {
        public void onComplete(String jsonString, Exception e, HashMap trackers);
    }

    public HashMap getTrackerMap() {
        return trackerMap;
    }

    public DatastreamsSettings getSettings() {
        return settings;
    }
}
