package org.keyscience.BackgroundTask;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;

import org.keyscience.Database.DatabaseHelper;
import org.keyscience.Database.EcoQuestDBContract;
import org.keyscience.SingletonPattern.User;
import org.keyscience.app.Constants;
import org.keyscience.app.ProfileUpdateActivity;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class UpdateProfileTask extends AsyncTask<String, Boolean, Boolean> {

    private String name;
    private String bio;
    private WeakReference<Context> contextWeakReference;

    public UpdateProfileTask(String name, String bio, Context context) {
        this.name = name;
        this.bio = bio;
        contextWeakReference = new WeakReference<>(context);
    }

    @Override
    protected Boolean doInBackground(String... strings) {
        try {
            if (userLogin(strings[0], strings[1])) {

                // update user instance
                User.getInstance().setName(name);
                User.getInstance().setBio(bio);

                //update local DB
                updateLocalDBProfile(User.getInstance().getUserID());

                // update remote DB
                updateRemoteDBProfile(strings[0], strings[1]);


                return true;

            } else {
                //failed to login
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

    }

    @Override
    protected void onPostExecute(Boolean successfulLogin) {

        if (successfulLogin) {
            // send broadcast to refresh UI
            Intent intentUpdatePoints = new Intent();
            intentUpdatePoints.setAction(Constants.PROFILE_CHANGED);
            LocalBroadcastManager.getInstance(contextWeakReference.get()).sendBroadcast(intentUpdatePoints);
            Toast.makeText(contextWeakReference.get(), "Profile Successfully Updated", Toast.LENGTH_LONG).show();

            ((ProfileUpdateActivity) contextWeakReference.get()).finish();

        } else {
            Toast.makeText(contextWeakReference.get(), "Failed to update profile", Toast.LENGTH_LONG).show();
        }
        super.onPostExecute(successfulLogin);
    }

    /**
     * Update user Name and Bio in SQLite DB
     *
     * @param userID of the user to be updated
     */
    private void updateLocalDBProfile(long userID) {

        DatabaseHelper databaseHelper = new DatabaseHelper(contextWeakReference.get());

        SQLiteDatabase db = databaseHelper.getWritableDatabase();

        // Create a map of values, where column names are the keys
        ContentValues values = new ContentValues();
        values.put(EcoQuestDBContract.UserTable.BIO, bio);
        values.put(EcoQuestDBContract.UserTable.NAME, name);

        String selection = EcoQuestDBContract.UserTable._ID + " = ?";
        String[] selectionArgs = {Long.toString(userID)};

        db.update(
                EcoQuestDBContract.UserTable.TABLE_NAME,
                values,
                selection,
                selectionArgs);
    }

    private void updateRemoteDBProfile(String user_login, String user_pass) throws IOException {
        HashMap<String, String> userCredentials = new HashMap<>();

        userCredentials.put("user_login", user_login);
        userCredentials.put("user_pass", user_pass);

        userCredentials.put("display_name", name);
        userCredentials.put("user_bio", bio);

        String urlParameters = getDataString(userCredentials);

        // POST CALL
        byte[] postData = new byte[0];
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
            postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
        }
        else
            postData = urlParameters.getBytes(Charset.forName("UTF-8"));

        int postDataLength = postData.length;

        String request = "http://www.keyscience.org/wp-content/app/userprofile/updateUserProfile.php";

        URL url = new URL( request );
        HttpURLConnection conn= (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setInstanceFollowRedirects(false);

        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("charset", "utf-8");
        conn.setRequestProperty("Content-Length", Integer.toString(postDataLength ));
        conn.setUseCaches(false);

        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
        wr.write( postData );

        // READ PHP OUTPUT
        String inputLine;
        InputStream in = conn.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));

        while ((inputLine = reader.readLine()) != null) {
            System.out.println(inputLine);
            if (!inputLine.equals("FAIL!")) {
                String readInputLine = inputLine;
            }
        }
        in.close();
    }

    private Boolean userLogin(String user_login, String user_pass) throws IOException {
        boolean loginSuccess = true;

        HashMap<String, String> userCredentials = new HashMap<>();

        userCredentials.put("user_login", user_login);
        userCredentials.put("user_pass", user_pass);

        String urlParameters = getDataString(userCredentials);

        // POST CALL
        byte[] postData = new byte[0];
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
            postData = urlParameters.getBytes(StandardCharsets.UTF_8);
        } else
            postData = urlParameters.getBytes(Charset.forName("UTF-8"));

        int postDataLength = postData.length;

        String request = "http://www.keyscience.org/wp-content/app/userLogin.php";

        URL url = new URL(request);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setInstanceFollowRedirects(false);

        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("charset", "utf-8");
        conn.setRequestProperty("Content-Length", Integer.toString(postDataLength));
        conn.setUseCaches(false);

        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
        wr.write(postData);

        // READ PHP OUTPUT
        InputStream in = conn.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));

        String inputLine;
        StringBuilder jsonString = new StringBuilder();
        while ((inputLine = reader.readLine()) != null) {

            jsonString.append(inputLine);

            if (inputLine.equals("FAIL!")) {
                loginSuccess = false;
            }
        }
        in.close();
        return loginSuccess;
    }

    private static String getDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");
            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }
        return result.toString();
    }

}
