package kr.co.icontrols.iotplatform;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserDetails;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserSession;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferListener;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferNetworkLossHandler;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferObserver;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferState;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.theartofdev.edmodo.cropper.CropImage;
import com.theartofdev.edmodo.cropper.CropImageView;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import kr.co.icontrols.iotplatform.AWS.Util;
import kr.co.icontrols.iotplatform.DataClass.UserInfo;
import kr.co.icontrols.iotplatform.Database.DBUtil;
import kr.co.icontrols.iotplatform.cognito.AppHelper;
import kr.co.icontrols.iotplatform.utils.DownloadImageTask;
import kr.co.icontrols.iotplatform.utils.HttpApi;
import kr.co.icontrols.iotplatform.utils.SharedPrefUtil;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

import static android.content.Intent.EXTRA_PHONE_NUMBER;
import static kr.co.icontrols.iotplatform.Database.DatabaseHelper.DATABASE_NAME;
import static kr.co.icontrols.iotplatform.PopupActivity.POPUP_BUNDLE;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.DebugLogOutput;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.DismissConnectDialog;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.ErrorLogOutput;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.WarnLogOutput;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.displayProgress;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.getCircleBitmap;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.showNotiMsg;
import static kr.co.icontrols.iotplatform.utils.Constants.EXTRA_DEVICE_ID;
import static kr.co.icontrols.iotplatform.utils.Constants.RESULT_INPUT_HP;
import static kr.co.icontrols.iotplatform.utils.Constants.RESULT_INPUT_NICKNAME;
import static kr.co.icontrols.iotplatform.utils.Constants.RESULT_RESEND_CONFIRM;
import static kr.co.icontrols.iotplatform.utils.Constants.RESULT_SIGN_OUT_CONFIRM;

public class ProfileUserActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "ProfileUserActivity";

    private TextView txtName, txtEmail, txtHp, txtEmailCertification, txtAutoLoginDescription;
    private ImageView imgProfile;
    private boolean isChangeData;

    //private CustomDialog customDialog;
    private AlertDialog userDialog;
    private ProgressDialog waitDialog;

    // Cognito user objects
    private CognitoUser user;
    private CognitoUserSession session;
    private CognitoUserDetails details;

    // User details
    private String username;

    // Reference to the utility class
    static Util util;
    // The TransferUtility is the primary class for managing transfer to S3
    private static TransferUtility transferUtility;
    private static TransferObserver observer;
    private String saveFileName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_profile_user);

        isChangeData = false;

        // Initializes TransferUtility, always do this before using it.
        observer = null;
        util = new Util();
        transferUtility = util.getTransferUtility(this);
        TransferNetworkLossHandler.getInstance(this);

        txtName = findViewById(R.id.txtName);
        txtEmail = findViewById(R.id.txtEmail);
        txtHp = findViewById(R.id.txtHp);
        txtAutoLoginDescription = findViewById(R.id.txtAutoLoginDescription);
        txtEmailCertification = findViewById(R.id.txtEmailCertification);

        imgProfile = findViewById(R.id.imgProfile);

        // Get the user name
        Bundle extras = getIntent().getExtras();
        username = AppHelper.getCurrUser();
        user = AppHelper.getPool().getUser(username);
        getDetails();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (SharedPrefUtil.getBoolean(SharedPrefUtil.AUTO_LOGIN, SharedPrefUtil.DEFAULT_AUTO_LOGIN)) {
            txtAutoLoginDescription.setText(getString(R.string.selected));
        } else {
            txtAutoLoginDescription.setText(getString(R.string.unselected));
        }
    }

    @Override
    protected void onPause() {
        if(observer != null) {
            observer.cleanTransferListener();
        }
        super.onPause();
    }

    @Override
    public void onBackPressed() {
        if(isChangeData) {
            setResult(RESULT_OK);
            finish();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public void onClick(View v) {
        /*
        final View fv = v;
        fv.setEnabled(false);
        Timer buttonTimer = new Timer();
        buttonTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            fv.setEnabled(true);
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {

                        }
                    }
                });
            }
        }, 500);
        */

        switch (v.getId()) {
            case R.id.btnBack:
                onBackPressed();
                break;
            case R.id.layoutEmail:
                if(UserInfo.confirmed) {
                    showNotiMsg(ProfileUserActivity.this,getString(R.string.snackbar_already_certification));
                } else {
                    Intent intent = new Intent(this, PopupActivity.class);
                    intent.putExtra(PopupActivity.POPUP_MODE, PopupActivity.MODE_YESNO);
                    intent.putExtra(PopupActivity.POPUP_TITLE_TEXT, "인증 요청 메일을 전송하시겠습니까?");
                    startActivityForResult(intent, RESULT_RESEND_CONFIRM);
                }
                break;
            case R.id.layoutChangePassword:
                startActivity(new Intent(this, ChangePasswordActivity.class));
                break;
            case R.id.layoutHp: {
                Intent intent = new Intent(this, PhoneNumChangeActivity.class);
                intent.putExtra(EXTRA_PHONE_NUMBER,txtHp.getText().toString());
                startActivityForResult(intent, RESULT_INPUT_HP);
                /*
                Intent intent = new Intent(this, PopupActivity.class);
                intent.putExtra(PopupActivity.POPUP_MODE, PopupActivity.MODE_INPUT);
                Bundle b = new Bundle();
                if (txtHp.getText().toString().isEmpty()) {
                    b.putString(PopupActivity.POPUP_INPUT, "");
                } else {
                    b.putString(PopupActivity.POPUP_INPUT, txtHp.getText().toString());
                }
                intent.putExtra(POPUP_BUNDLE, b);
                intent.putExtra(PopupActivity.POPUP_TITLE_TEXT, getString(R.string.change_hp));
                startActivityForResult(intent, RESULT_INPUT_HP);
                 */
                }
                break;
            case R.id.layoutAutoLogin: {
                Intent autologinIntent = new Intent(this, PopupActivity.class);
                autologinIntent.putExtra(PopupActivity.POPUP_MODE, PopupActivity.MODE_AUTO_LOGIN);
                startActivity(autologinIntent);
                }
                break;
            case R.id.layoutLogout:
                UserInfo.clear();
                SharedPrefUtil.putBoolean(SharedPrefUtil.AUTO_LOGIN,false);
                user.signOut();
                restartApp();
                break;
            case R.id.layoutSignOut:{
                Intent intent = new Intent(this, PopupActivity.class);
                intent.putExtra(PopupActivity.POPUP_MODE, PopupActivity.MODE_YESNO);
                intent.putExtra(PopupActivity.POPUP_TITLE_TEXT, getString(R.string.popup_sign_out_confirm));
                intent.putExtra(PopupActivity.POPUP_OK_BUTTON_TEXT, getString(R.string.signout2));
                startActivityForResult(intent, RESULT_SIGN_OUT_CONFIRM);
                /*
                Intent intent = new Intent(this, PopupActivity.class);
                intent.putExtra(PopupActivity.POPUP_MODE, PopupActivity.MODE_INPUT);
                Bundle b = new Bundle();
                b.putString(PopupActivity.POPUP_INPUT, "");
                intent.putExtra(POPUP_BUNDLE, b);
                intent.putExtra(PopupActivity.POPUP_TITLE_TEXT, getString(R.string.popup_sign_out_confirm));
                startActivityForResult(intent, RESULT_SIGN_OUT_CONFIRM);
                 */
                }
                break;
            case R.id.imgProfile:
                selectImage();
                break;
            case R.id.txtName:
                //showUserDetail(COGNITO_NICKNAME, txtName.getText().toString());
                {
                Intent intent = new Intent(this, PopupActivity.class);
                intent.putExtra(PopupActivity.POPUP_MODE, PopupActivity.MODE_INPUT);
                intent.putExtra(PopupActivity.POPUP_INPUT_MIN, 4);
                intent.putExtra(PopupActivity.POPUP_INPUT_MAX, 8);
                Bundle b = new Bundle();
                if (txtName.getText().toString().isEmpty()) {
                    b.putString(PopupActivity.POPUP_INPUT, "");
                } else {
                    b.putString(PopupActivity.POPUP_INPUT, txtName.getText().toString());
                }
                intent.putExtra(POPUP_BUNDLE, b);
                intent.putExtra(PopupActivity.POPUP_TITLE_TEXT, getString(R.string.change_nickname));
                startActivityForResult(intent, RESULT_INPUT_NICKNAME);
                }
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // handle result of CropImageActivity
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
            CropImage.ActivityResult result = CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK) {
                //((ImageView) findViewById(R.id.imgProfile)).setImageURI(result.getUri());
                Bitmap bitmap = null;
                try {
                    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), result.getUri());
                    ((ImageView) findViewById(R.id.imgProfile)).setImageBitmap(getCircleBitmap(bitmap));

                    Date day = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.KOREA);
                    saveFileName = String.valueOf("user_profile_"+sdf.format(day)+".jpg");
                    String targetDir = Environment.getExternalStorageDirectory().toString();
                    File file = new File(targetDir+"/"+saveFileName);
                    file.createNewFile();
                    OutputStream  out = new FileOutputStream(file);
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                    beginUpload(file);
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    ((ImageView) findViewById(R.id.imgProfile)).setImageURI(result.getUri());
                    showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_profile_img));
                }
            } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
                showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_profile_img));
            }
        } else if(requestCode == RESULT_INPUT_NICKNAME) {
            if (resultCode == RESULT_OK) {
                Bundle b = data.getBundleExtra(POPUP_BUNDLE);
                if(b != null) {
                    try {
                        String newValue = b.getString(PopupActivity.POPUP_INPUT);
                        if(!newValue.equals(UserInfo.nickname)) {
                            changeProfile("",newValue,"");
                        }
                    } catch (Exception e) {
                        // Log failure
                        showNotiMsg(ProfileUserActivity.this,getString(R.string.snackbar_fail_change_nickname));
                    }
                } else {
                    showNotiMsg(ProfileUserActivity.this,getString(R.string.snackbar_fail_change_nickname));
                }
            }
        } else if(requestCode == RESULT_INPUT_HP) {
            if (resultCode == RESULT_OK) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        isChangeData = true;
                        txtHp.setText(UserInfo.phoneNumber);
                    }
                });
                /*
                Bundle b = data.getBundleExtra(POPUP_BUNDLE);
                if(b != null) {
                    try {
                        String newValue = b.getString(PopupActivity.POPUP_INPUT);
                        if(!newValue.equals(UserInfo.phoneNumber)) {
                            changeProfile("","",newValue);
                        }
                    } catch (Exception e) {
                        // Log failure
                        showNotiMsg(ProfileUserActivity.this,getString(R.string.snackbar_fail_change_hp));
                    }
                } else {
                    showNotiMsg(ProfileUserActivity.this,getString(R.string.snackbar_fail_change_hp));
                }
                 */
            }
        } else if(requestCode == RESULT_SIGN_OUT_CONFIRM) {
            if (resultCode == RESULT_OK) {
                /*
                Bundle b = data.getBundleExtra(POPUP_BUNDLE);
                if(b != null) {
                    try {
                        String newValue = b.getString(PopupActivity.POPUP_INPUT);
                        signOut(newValue);
                    } catch (Exception e) {
                        // Log failure
                        showNotiMsg(ProfileUserActivity.this,"회원 탈퇴에 실패하였습니다.");
                    }
                } else {
                    showNotiMsg(ProfileUserActivity.this,"회원 탈퇴에 실패하였습니다.");
                }
                 */
                UserInfo.clear();
                signOut("");
            }
        } else if(requestCode == RESULT_RESEND_CONFIRM) {
            if (resultCode == RESULT_OK) {
                requestConfirmUser();
            }
        }
    }

    private void signOut(final String password) {
        try{
            displayProgress(ProfileUserActivity.this, "","");
            HttpApi.deleteUserInfo(UserInfo.uid, password, new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    ErrorLogOutput(TAG, "HttpApi.deleteUserInfo(onFailure)\n" + e.toString());
                    showNotiMsg(ProfileUserActivity.this, "회원 탈퇴에 실패하였습니다.");
                    DismissConnectDialog();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if(response.code() == HttpApi.HTTP_NO_CONTENT) {
                        WarnLogOutput(TAG, "HttpApi.deleteUserInfo(onResponse) HTTP_NO_CONTENT");
                        showNotiMsg(ProfileUserActivity.this, "회원 탈퇴을 하였습니다.");
                        SharedPrefUtil.reset();
                        DBUtil.removeAll();
                        deleteDatabase(DATABASE_NAME);
                        IotPlatformApplication.getInstance().clearApplicationData();
                        user.signOut();
                        restartApp();
                    } else {
                        ErrorLogOutput(TAG, "HttpApi.deleteUserInfo(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                        showNotiMsg(ProfileUserActivity.this, "회원 탈퇴에 실패하였습니다.");
                        try {
                            JSONObject json_data = new JSONObject(response.body().string());
                            ErrorLogOutput(TAG, "HttpApi.deleteUserInfo(onResponse) body : " + json_data.toString());
                        } catch (JSONException e) {
                            ErrorLogOutput(TAG, "HttpApi.deleteUserInfo(onResponse) JSONException : " + e.toString());
                        }
                    }
                    DismissConnectDialog();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            ErrorLogOutput(TAG, "HttpApi.deleteUserInfo(Exception)\n" + e.toString());
            showNotiMsg(ProfileUserActivity.this, "회원 탈퇴에 실패하였습니다.");
            DismissConnectDialog();
        }
    }

    private void requestConfirmUser() {
        try {
            displayProgress(ProfileUserActivity.this, "","");
            HttpApi.requestConfirmUser(true, true, UserInfo.email, new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onFailure)\n" + e.toString());
                    showNotiMsg(ProfileUserActivity.this, "인증 요청에 실패하였습니다.");
                    DismissConnectDialog();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if(response.code() == HttpApi.HTTP_NO_CONTENT) {
                        WarnLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) HTTP_NO_CONTENT");
                        showNotiMsg(ProfileUserActivity.this, "인증을 요청을 하였습니다.");
                    } else {
                        ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                        showNotiMsg(ProfileUserActivity.this, "인증 요청에 실패하였습니다.");
                        try {
                            JSONObject json_data = new JSONObject(response.body().string());
                            ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) body : " + json_data.toString());
                        } catch (JSONException e) {
                            ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) JSONException : " + e.toString());
                        }
                    }
                    DismissConnectDialog();
                }
            });
        } catch (Exception e){
            e.printStackTrace();
            ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(Exception)\n" + e.toString());
            showNotiMsg(ProfileUserActivity.this, "인증 요청에 실패하였습니다.");
            DismissConnectDialog();
        }
    }

    private void changeProfile(final String profile, final String nickName, final String phoneNumber) {
        try {
            displayProgress(ProfileUserActivity.this, "","");
            HttpApi.changeUserInfo(profile, nickName, phoneNumber, UserInfo.pushAccess, UserInfo.autoUpdate, "", new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    ErrorLogOutput(TAG, "HttpApi.changeUserInfo(onFailure)\n" + e.toString());
                    if(!profile.isEmpty()) {
                        showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_profile_img));
                    } else if(!nickName.isEmpty()) {
                        showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_nickname));
                    } else if(!phoneNumber.isEmpty()) {
                        showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_hp));
                    }
                    DismissConnectDialog();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if(response.code() == HttpApi.HTTP_NO_CONTENT) {
                        WarnLogOutput(TAG, "HttpApi.changeUserInfo(onResponse) HTTP_NO_CONTENT");
                        isChangeData = true;
                        if(!profile.isEmpty()) {
                            UserInfo.profile = profile;
                            showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_successed_change_profile_img));
                        } else if(!nickName.isEmpty()) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    txtName.setText(nickName);
                                }
                            });
                            UserInfo.nickname = nickName;
                            showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_successed_change_nickname));
                        } else if(!phoneNumber.isEmpty()) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    txtHp.setText(phoneNumber);
                                }
                            });
                            UserInfo.phoneNumber = phoneNumber;
                            showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_successed_change_hp));
                        }
                    } else {
                        ErrorLogOutput(TAG, "HttpApi.changeUserInfo(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                        try {
                            JSONObject json_data = new JSONObject(response.body().string());
                            ErrorLogOutput(TAG, "HttpApi.changeUserInfo(onResponse) body : " + json_data.toString());
                        } catch (JSONException e) {
                            ErrorLogOutput(TAG, "HttpApi.changeUserInfo(onResponse) JSONException : " + e.toString());
                        }
                        if(!profile.isEmpty()) {
                            showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_profile_img));
                        } else if(!nickName.isEmpty()) {
                            showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_nickname));
                        } else if(!phoneNumber.isEmpty()) {
                            showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_hp));
                        }
                    }
                    DismissConnectDialog();
                }
            });
        } catch (Exception e){
            e.printStackTrace();
            ErrorLogOutput(TAG, "HttpApi.changeUserInfo(Exception)\n" + e.toString());
            DismissConnectDialog();
            if(!profile.isEmpty()) {
                showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_profile_img));
            } else if(!nickName.isEmpty()) {
                showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_nickname));
            } else if(!phoneNumber.isEmpty()) {
                showNotiMsg(ProfileUserActivity.this, getString(R.string.snackbar_fail_change_hp));
            }
        }
    }


    // Get user details from CIP serviceN
    private void getDetails() {
        //AppHelper.getPool().getUser(username).getDetailsInBackground(detailsHandler);

        // show The Image in a ImageView
        if(UserInfo.profile != null && !UserInfo.profile.isEmpty()) {
            new DownloadImageTask(findViewById(R.id.imgProfile)).execute(UserInfo.profile);
        } else {
            ((ImageView)findViewById(R.id.imgProfile)).setImageResource(R.drawable.profile_thum_176);
        }

        // set Value for component
        txtEmail.setText(UserInfo.email);
        txtHp.setText(UserInfo.phoneNumber);
        txtName.setText(UserInfo.nickname);
        if (UserInfo.confirmed) {
            txtEmailCertification.setText(getString(R.string.cert));
        } else {
            txtEmailCertification.setText(getString(R.string.no_cert));
        }
    }

    /*
    // Show user attributes from CIP service
    private void showAttributes() {
        int count = AppHelper.getItemCount();
        for (int i = 0; i < count; i++) {
            ItemToDisplay it = AppHelper.getItemForDisplay(i);
            if (it.getLabelText().equals(COGNITO_EMAIL)) {
                txtEmail.setText(it.getDataText());
                if (AppHelper.isEmailVerified()) {
                    txtEmailCertification.setText(getString(R.string.cert));
                } else {
                    txtEmailCertification.setText(getString(R.string.no_cert));
                }
            } else if (it.getLabelText().equals(COGNITO_PHONENUMBER)) {
                txtHp.setText(it.getDataText());
            } else if (it.getLabelText().equals(COGNITO_NICKNAME)) {
                txtName.setText(it.getDataText());
            }
        }
    }

    // Update attributes
    private void updateAttribute(String attributeType, String attributeValue) {

        if(attributeType == null || attributeType.length() < 1) {
            return;
        }
        CognitoUserAttributes updatedUserAttributes = new CognitoUserAttributes();
        updatedUserAttributes.addAttribute(attributeType, attributeValue);
        Toast.makeText(getApplicationContext(), attributeType + ": " + attributeValue, Toast.LENGTH_LONG);
        showWaitDialog("Updating...");
        AppHelper.getPool().getUser(AppHelper.getCurrUser()).updateAttributesInBackground(updatedUserAttributes, updateHandler);
    }

    // Delete attribute
    private void deleteAttribute(String attributeName) {
        showWaitDialog("Deleting...");
        List<String> attributesToDelete = new ArrayList<>();
        attributesToDelete.add(attributeName);
        AppHelper.getPool().getUser(AppHelper.getCurrUser()).deleteAttributesInBackground(attributesToDelete, deleteHandler);
    }

    GetDetailsHandler detailsHandler = new GetDetailsHandler() {
        @Override
        public void onSuccess(CognitoUserDetails cognitoUserDetails) {
            closeWaitDialog();
            // Store details in the AppHandler
            AppHelper.setUserDetails(cognitoUserDetails);
            showAttributes();
            // Trusted devices?
            handleTrustedDevice();
        }

        @Override
        public void onFailure(Exception exception) {
            closeWaitDialog();
            showDialogMessage("Could not fetch user details!", AppHelper.formatException(exception), true);
        }
    };

    UpdateAttributesHandler updateHandler = new UpdateAttributesHandler() {
        @Override
        public void onSuccess(List<CognitoUserCodeDeliveryDetails> attributesVerificationList) {
            // Update successful
            if(attributesVerificationList.size() > 0) {
                showDialogMessage("Updated", "The updated attributes has to be verified",  false);
            }
            getDetails();
        }

        @Override
        public void onFailure(Exception exception) {
            // Update failed
            closeWaitDialog();
            showDialogMessage("Update failed", AppHelper.formatException(exception), false);
        }
    };

    GenericHandler deleteHandler = new GenericHandler() {
        @Override
        public void onSuccess() {
            closeWaitDialog();
            // Attribute was deleted
            Toast.makeText(getApplicationContext(), "Deleted", Toast.LENGTH_SHORT);

            // Fetch user details from the the service
            getDetails();
        }

        @Override
        public void onFailure(Exception e) {
            closeWaitDialog();
            // Attribute delete failed
            showDialogMessage("Delete failed", AppHelper.formatException(e), false);

            // Fetch user details from the service
            getDetails();
        }
    };

    GenericHandler trustedDeviceHandler = new GenericHandler() {
        @Override
        public void onSuccess() {
            // Close wait dialog
            closeWaitDialog();
        }

        @Override
        public void onFailure(Exception exception) {
            closeWaitDialog();
            showDialogMessage("Failed to update device status", AppHelper.formatException(exception), true);
        }
    };

    private void handleTrustedDevice() {
        CognitoDevice newDevice = AppHelper.getNewDevice();
        if (newDevice != null) {
            AppHelper.newDevice(null);
            trustedDeviceDialog(newDevice);
        }
    }

    private void updateDeviceStatus(CognitoDevice device) {
        device.rememberThisDeviceInBackground(trustedDeviceHandler);
    }

    private void trustedDeviceDialog(final CognitoDevice newDevice) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Remember this device?");
        //final EditText input = new EditText(UserActivity.this);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT);

        //input.setLayoutParams(lp);
        //input.requestFocus();
        //builder.setView(input);

        builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    //String newValue = input.getText().toString();
                    showWaitDialog("Remembering this device...");
                    updateDeviceStatus(newDevice);
                    userDialog.dismiss();
                } catch (Exception e) {
                    // Log failure
                }
            }
        }).setNegativeButton("No", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    userDialog.dismiss();
                } catch (Exception e) {
                    // Log failure
                }
            }
        });
        userDialog = builder.create();
        userDialog.show();
    }


    private void showUserDetail(final String attributeType, final String attributeValue) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(attributeType);
        final EditText input = new EditText(ProfileUserActivity.this);
        input.setText(attributeValue);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT);

        input.setLayoutParams(lp);
        input.requestFocus();
        builder.setView(input);

        builder.setNeutralButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    String newValue = input.getText().toString();
                    if(!newValue.equals(attributeValue)) {
                        showWaitDialog("Updating...");
                        updateAttribute(AppHelper.getSignUpFieldsC2O().get(attributeType), newValue);
                    }
                    userDialog.dismiss();
                } catch (Exception e) {
                    // Log failure
                }
            }
        }).setPositiveButton("Delete", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    userDialog.dismiss();
                    deleteAttribute(AppHelper.getSignUpFieldsC2O().get(attributeType));
                } catch (Exception e) {
                    // Log failure
                }
            }
        });
        userDialog = builder.create();
        userDialog.show();
    }

    private void showWaitDialog(String message) {
        closeWaitDialog();
        waitDialog = new ProgressDialog(this);
        waitDialog.setTitle(message);
        waitDialog.show();
    }

    private void showDialogMessage(String title, String body, final boolean exit) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(title).setMessage(body).setNeutralButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    userDialog.dismiss();
                    if (exit) {
                        exit();
                    }
                } catch (Exception e) {
                    // Log failure
                    Log.e(TAG, " -- Dialog dismiss failed");
                    if (exit) {
                        exit();
                    }
                }
            }
        });
        userDialog = builder.create();
        userDialog.show();
    }

    private void closeWaitDialog() {
        try {
            waitDialog.dismiss();
        } catch (Exception e) {
            //
        }
    }

    private void exit() {
        Intent intent = new Intent();
        if (username == null)
            username = "";
        intent.putExtra("name", username);
        setResult(RESULT_OK, intent);
        finish();
    }
    */

    private void restartApp() {
        Intent intent = new Intent(this, SplashActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        finish();
    }

    private void selectImage() {
        CropImage.activity()
                .setGuidelines(CropImageView.Guidelines.ON)
                .setActivityTitle("My Crop")
                .setCropShape(CropImageView.CropShape.OVAL)
                .setCropMenuCropButtonTitle("Done")
                .setRequestedSize(400, 400)
                .setCropMenuCropButtonIcon(R.drawable.icon_crop)
                .setAspectRatio(1,1)
                .setScaleType(CropImageView.ScaleType.FIT_CENTER)
                .start(this);
    }

    public static String getPath(final Context context, final Uri uri) {
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
                    if ("primary".equalsIgnoreCase(type)) {
                        return Environment.getExternalStorageDirectory() + "/" + split[1];
                    }
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri)) {
                    final String id = DocumentsContract.getDocumentId(uri);
                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                    return getDataColumn(context, contentUri, null, null);
                }
                // MediaProvider
                else if (isMediaDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
                    Uri contentUri = null;
                    if ("image".equals(type)) {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(type)) {
                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(type)) {
                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }
                    final String selection = "_id=?";
                    final String[] selectionArgs = new String[]{
                            split[1]
                    };
                    return getDataColumn(context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)
            else if ("content".equalsIgnoreCase(uri.getScheme())) {
                return getDataColumn(context, uri, null, null);
            }
            // File
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
        }
        return null;
    }

    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /*
     * A TransferListener class that can listen to a upload task and be notified
     * when the status changes.
     */
    class UploadListener implements TransferListener {

        // Simply updates the UI list when notified.
        @Override
        public void onError(int id, Exception e) {
            ErrorLogOutput(TAG, "S3->Error during upload: " + id + "\ne : " + e);
        }

        @Override
        public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
            DebugLogOutput(TAG, String.format("S3->onProgressChanged: %d, total: %d, current: %d",
                    id, bytesTotal, bytesCurrent));
        }

        @Override
        public void onStateChanged(int id, TransferState newState) {
            DebugLogOutput(TAG, "S3->onStateChanged: " + id + ", " + newState);
            if(newState == TransferState.COMPLETED){
                changeProfile("https://bi-home-admin-factory-app-314854109580.s3.ap-northeast-2.amazonaws.com/user_profile/"+UserInfo.uid+"/"+saveFileName,"","");
            }
        }
    }

    private void beginUpload(File file) {

        if(observer != null) {
            observer.cleanTransferListener();
        }

        observer = transferUtility.upload(
                "bi-home-admin-factory-app-314854109580" + "/user_profile/" + UserInfo.uid,
                file.getName(),
                file,
                new ObjectMetadata(),
                null,
                new UploadListener()
        );

        /*
         * Note that usually we set the transfer listener after initializing the
         * transfer. However it isn't required in this sample app. The flow is
         * click upload button -> start an activity for image selection
         * startActivityForResult -> onActivityResult -> beginUpload -> onResume
         * -> set listeners to in progress transfers.
         */
        // observer.setTransferListener(new UploadListener());
    }
}