package com.cc.infosur.main;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.util.Log;

import com.cc.infosur.R;
import com.cc.infosur.greendao.DaoMaster;
import com.cc.infosur.greendao.DaoSession;
import com.cc.infosur.greendao.Link;
import com.cc.infosur.greendao.LinkDao;
import com.cc.infosur.greendao.Node;
import com.cc.infosur.greendao.NodeDao;
import com.cc.infosur.greendao.ParkInfo;
import com.cc.infosur.greendao.ParkInfoDao;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
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.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by STEVEN on 16/11/2014.
 */
// ----------
public class LoadRoutingTask extends AsyncTask<Void, Void, Boolean> {

    private SQLiteDatabase db;
    private DaoMaster.DevOpenHelper helper;
    private DaoSession daoSession;
    private DaoMaster daoMaster;
    private NodeDao nodeDao;
    private LinkDao linkDao;
    private ParkInfoDao parkInfoDao;
    private Context context;
    private int etpParkId;
    List<Double> nodeLatitudes = new ArrayList<Double>();
    List<Double> nodeLongitudes = new ArrayList<Double>();

    // Long linkId = 1L;
    Long nodeId = 0L;

    /**
     * Function convertStreamToString()
     * @param is
     * @return
     */
    private String convertStreamToString(InputStream is) {

        BufferedReader reader = new BufferedReader(
                new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }


    /**
     * Function addNode()
     * @param latitude
     * @param longitude
     * @param mainNode
     * @param linkForward
     * @param positionForward
     * @param linkBackward
     * @param positionBackward
     * @return
     */
    private Node addNode(Double latitude, Double longitude, Boolean mainNode, Long linkForward, int positionForward, Long linkBackward, int positionBackward) {

        if (mainNode) {

            if (latitude == -26.180895000437406 && longitude == 20.8199594441027) {
                Log.i("PATH", "NODE FOUND");
            }

            for (int i = 0; i < nodeLatitudes.size(); i++) {
                if (nodeLatitudes.get(i).equals(latitude)
                        && nodeLongitudes.get(i).equals(longitude)) {
                    if (latitude == -26.180895000437406
                            && longitude == 20.8199594441027) {
                        Log.i("PATH", "NODE REPEAT " + i);
                    }
                    return nodeDao.load((long) i);
                }
            }
            // List<Node> nodes = nodeDao
            // .queryBuilder()
            // .where(Properties.Longitude.eq(longitude),
            // Properties.Latitude.eq(latitude)).list();
            // if (nodes.size() > 0) {
            // if (latitude == -26.180895000437406 && longitude ==
            // 20.8199594441027){
            // Log.i("PATH", "NODE REPEAT");
            // }
            // return nodes.get(0);
            // }
        }
        Node node = new Node();
        node.setId(nodeId++);
        nodeLatitudes.add(latitude);
        nodeLongitudes.add(longitude);
        node.setLatitude(latitude);
        node.setLongitude(longitude);
        node.setLinkForward(linkForward);
        node.setPositionForward(positionForward);
        node.setLinkBackward(linkBackward);
        node.setPositionBackward(positionBackward);
        // Log.i("JSON", "Node to insert: " + node.getId() + " " +
        // node.getLatitude() + " " + node.getLongitude());
        nodeDao.insert(node);
        if (latitude == -26.180895000437406 && longitude == 20.8199594441027) {
            Log.i("PATH","NODE: " + node.getId() + " - " + node.getLatitude()+ "," + node.getLongitude());
        }
        return node;
    }


    /**
     * Constructor
     * @param Context
     */
    public LoadRoutingTask(Context Context) {
        super();
        context = Context;
    }


    /**
     * Function onPreExecute() - AsyncTask 1 / 3
     */
    ProgressDialog pDialog;
    protected void onPreExecute() {
        pDialog = new ProgressDialog(context);
        pDialog.setTitle(context.getResources().getString(R.string.download));
        pDialog.setMessage("Loading routing network...");
        pDialog.setProgressStyle(pDialog.STYLE_HORIZONTAL);
        pDialog.setCancelable(false);
        pDialog.setCanceledOnTouchOutside(false);
        pDialog.show();
    }


    /**
     * Function doInBackground() - AsyncTask 2 / 3
     * @param params
     * @return
     */
    @Override
    protected Boolean doInBackground(Void... params) {

        // Prepare db
        helper = new DaoMaster.DevOpenHelper(context, "tripdb", null);
        db = helper.getWritableDatabase();
        daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
        nodeDao = daoSession.getNodeDao();
        linkDao = daoSession.getLinkDao();
        parkInfoDao = daoSession.getParkInfoDao();

        if(parkInfoDao.loadAll().size() != 0) {
            etpParkId = parkInfoDao.loadAll().get(0).getEtpParkId();
        }

        String jsonStr = null;

        // Create a new HttpClient and Post Header
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://sensa-demo.tripalacarte.com/frontend/json/parks/"+etpParkId+"/roads.json");


        System.out.println("******************"+"http://sensa-demo.tripalacarte.com/frontend/json/parks/"+etpParkId+"/roads.json");
        http://sensa-demo.tripalacarte.com/frontend/json/parks/"+etpParkId+"/roads.json

        try {

            System.out.println(" ++ SENSA ++ :: LoadActivity :: httppost :: " + httppost);

            // Execute HTTP Post Request
            HttpResponse response = httpclient.execute(httppost);

            // Get the string
            HttpEntity entity = response.getEntity();

            if (entity != null) {

                // A Simple JSON Response Read
                InputStream instream = entity.getContent();
                jsonStr = convertStreamToString(instream);
                // now you have the string representation of the HTML
                // request
                instream.close();
            }

        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
        } catch (IOException e) {
            // TODO Auto-generated catch block
        }


        // Delete before load
        nodeDao.deleteAll();
        linkDao.deleteAll();

        try {
            JSONObject networkObject = new JSONObject(jsonStr);

            JSONArray features = networkObject.getJSONArray("features");

            // Progress Dialog - Length Array
            pDialog.setMax(features.length());

            for (int i = 0; i < features.length(); i++) {

                JSONObject feature = features.getJSONObject(i);
                JSONObject properties = feature.getJSONObject("properties");
                // if (!properties.getString("Class").equals("Main"))
                // continue;
                JSONObject geometry = feature.getJSONObject("geometry");
                // JSONArray coordinates = geometry.getJSONArray("coordinates");
                // JSONArray coordinatesArray = coordinates.getJSONArray(0);
                // JSONArray nodeCoordinates = coordinatesArray.getJSONArray(0);

                JSONArray coordinatesArray = geometry.getJSONArray("coordinates");
                JSONArray nodeCoordinates = coordinatesArray.getJSONArray(0);

                // System.out.println(" SENSA :: nodeCoordinates :: " + nodeCoordinates);

                Node nodeFrom = addNode(nodeCoordinates.getDouble(1), nodeCoordinates.getDouble(0), true, 0L, 0, 0L, 0);
                nodeCoordinates = coordinatesArray.getJSONArray(coordinatesArray.length() - 1);
                Node nodeTo = addNode(nodeCoordinates.getDouble(1), nodeCoordinates.getDouble(0), true, 0L, 0, 0L, 0);

                Link linkF = new Link();
                Link linkB = null;
                // link.setId(linkId++);
                if(properties.has("Shape_Leng")) linkF.setLength(properties.getDouble("Shape_Leng"));
                if(properties.has("SPEEDKM")) linkF.setSpeed(properties.getDouble("SPEEDKM"));
                linkF.setNodeFrom(nodeFrom);
                linkF.setNodeTo(nodeTo);
                linkDao.insert(linkF);

                if (properties.getString("DIRECTION").equals("Two-ways")) {
                    linkB = new Link();
                    // link.setId(linkId++);
                    if(properties.has("Shape_Leng")) linkB.setLength(properties.getDouble("Shape_Leng"));
                    if(properties.has("SPEEDKM")) linkB.setSpeed(properties.getDouble("SPEEDKM"));
                    linkB.setNodeFrom(nodeTo);
                    linkB.setNodeTo(nodeFrom);
                    linkDao.insert(linkB);
                }

                if (coordinatesArray.length() > 2) {
                    for (int j = 1; j < coordinatesArray.length() - 1; j++) {
                        nodeCoordinates = coordinatesArray.getJSONArray(j);
                        if (properties.getString("DIRECTION").equals(
                                "Two-ways")) {
                            addNode(nodeCoordinates.getDouble(1),
                                    nodeCoordinates.getDouble(0), false,
                                    linkF.getId(), j, linkB.getId(),
                                    coordinatesArray.length() - (j + 1));
                        } else {
                            addNode(nodeCoordinates.getDouble(1),
                                    nodeCoordinates.getDouble(0), false,
                                    linkF.getId(), j, 0L, 0);
                        }
                    }
                }

                // Progress Dialog - Loading
                pDialog.setProgress(i+1);

            }

            Log.i("JSON", "Number of nodes: " + nodeDao.count() + "\nNumber of links: " + linkDao.count());

        } catch (JSONException e) {
            Log.i("JSON", e.getMessage());
            return false;
        }

        return true;
    }


    /**
     * Function onPostExecute() - AsyncTask 3 / 3
     * @param result
     */
    protected void onPostExecute(Boolean result) {

        pDialog.dismiss();

        if (result) {
            new AlertDialog.Builder(context)
                    .setTitle("Routing Network Loaded")
                    .setNegativeButton("OK",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,
                                                    int which) {
                                    dialog.dismiss();
                                }
                            }).show();
        } else {
            new AlertDialog.Builder(context)
                    .setTitle("JSON Exception")
                    .setNegativeButton("OK",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,
                                                    int which) {
                                    dialog.dismiss();
                                }
                            }).show();
        }

    }

}

