package co.pixelbeard.theanfieldwrap.login;

import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import com.rw.keyboardlistener.KeyboardUtils;

import org.parceler.Parcels;

import java.util.List;

import br.com.simplepass.loadingbutton.customViews.CircularProgressButton;
import butterknife.BindView;
import butterknife.ButterKnife;
import co.pixelbeard.theanfieldwrap.R;
import co.pixelbeard.theanfieldwrap.customView.PBInputField;
import co.pixelbeard.theanfieldwrap.data.Device;
import co.pixelbeard.theanfieldwrap.data.source.DataRepository;
import co.pixelbeard.theanfieldwrap.data.source.local.LocalRepository;
import co.pixelbeard.theanfieldwrap.data.source.remote.RemoteRepository;
import co.pixelbeard.theanfieldwrap.devices.DevicesActivity;
import co.pixelbeard.theanfieldwrap.dialog.LoadingDialog;
import co.pixelbeard.theanfieldwrap.dialog.twoButton.TwoButtonDialogListener;
import co.pixelbeard.theanfieldwrap.forgotPassword.ForgotPasswordActivity;
import co.pixelbeard.theanfieldwrap.home.HomeActivity;
import co.pixelbeard.theanfieldwrap.signUp.SignUpActivity;
import co.pixelbeard.theanfieldwrap.utils.ActivityExtraTags;
import co.pixelbeard.theanfieldwrap.utils.ActivityRequestCodes;
import co.pixelbeard.theanfieldwrap.utils.AnimUtils;
import co.pixelbeard.theanfieldwrap.utils.BaseActivity;
import co.pixelbeard.theanfieldwrap.utils.ConnectionUtils;
import co.pixelbeard.theanfieldwrap.utils.DialogUtils;
import co.pixelbeard.theanfieldwrap.utils.FontUtils;
import co.pixelbeard.theanfieldwrap.utils.TawController;
import co.pixelbeard.theanfieldwrap.walkthrough.WalkthroughActivity;
import io.realm.Realm;

public class LoginActivity extends BaseActivity implements LoginContract.View {

    private static final String TAG = LoginActivity.class.getSimpleName();

    @BindView(R.id.ll_back)
    LinearLayout llBack;
    @BindView(R.id.btn_login)
    CircularProgressButton btnLogin;
    @BindView(R.id.btn_forgot_password)
    Button btnForgotPassword;
    @BindView(R.id.btn_skip)
    Button btnSkip;
    @BindView(R.id.pb_email)
    PBInputField pbEmail;
    @BindView(R.id.pb_password)
    PBInputField pbPassword;

    @BindView(R.id.txt_already_got_account)
    TextView txtAlreadyGotAccount;

    @BindView(R.id.ll_no_internet_header)
    LinearLayout llNoInternetHeader;
    @BindView(R.id.txt_no_internet_header)
    TextView txtNoInternetHeader;


    private boolean isFromGuest;
    private boolean skipLoginPressed = false;
    private LoadingDialog loadingDialog;
    private LoginContract.Presenter mPresenter;

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

        ButterKnife.bind(this);

        new LoginPresenter(this, new DataRepository(new LocalRepository(Realm.getDefaultInstance()), new RemoteRepository()));

        isFromGuest = getIntent().getBooleanExtra(ActivityExtraTags.BOOL_FROM_GUEST, false);

        setButtonFont();
        setButtonClickListener();

        setTextViewFont();

        setInputFieldFont();
        setInputFieldImeListener();
        setInputFieldTextWatcher();
    }

    @Override
    protected void onResume() {
        super.onResume();
        TawController.setCurrentPage(TAG);

        if (isFromGuest) {
            btnSkip.setVisibility(View.GONE);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        btnLogin.dispose();
    }

    private void setButtonFont() {
        btnLogin.setTypeface(FontUtils.getInstance().getDinAlternateBold());
        btnForgotPassword.setTypeface(FontUtils.getInstance().getDinCondensedBold());
        btnSkip.setTypeface(FontUtils.getInstance().getDinCondensedBold());
    }

    private void setButtonClickListener() {

        llBack.setOnClickListener(v -> mPresenter.backClicked());

        btnSkip.setOnClickListener(v -> {
            skipLoginPressed = true;
            btnSkip.setEnabled(false);
            new Handler().postDelayed(() -> {
                if (!isFinishing()) {
                    btnSkip.setEnabled(true);
                }
            }, 200);
            mPresenter.skipLoginClicked();
        });

        btnForgotPassword.setOnClickListener(v -> {
            String email = "";
            if (pbEmail != null) {
                email = pbEmail.getText();
            }
            mPresenter.forgotPasswordClicked(email);
        });

        btnLogin.setOnClickListener(v -> {
            if (pbEmail != null && pbPassword != null) {
                mPresenter.loginClicked(pbEmail.getText(), pbPassword.getText(), isFromGuest);
            }
        });
    }

    private void setTextViewFont() {
        txtNoInternetHeader.setTypeface(FontUtils.getInstance().getDinAlternateBold());
        txtAlreadyGotAccount.setTypeface(FontUtils.getInstance().getDinAlternateBold());
        txtNoInternetHeader.setText(getString(R.string.no_internet_connection));
    }

    private void setInputFieldFont() {
        pbEmail.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
        pbEmail.setTooltipTypeface(FontUtils.getInstance().getDinAlternateBold());
        pbEmail.setEditTextTypeface(FontUtils.getInstance().getDinAlternateBold());
        pbEmail.setTextInputTypeface(FontUtils.getInstance().getDinAlternateBold());

        pbPassword.setTooltipTypeface(FontUtils.getInstance().getDinAlternateBold());
        pbPassword.setEditTextTypeface(FontUtils.getInstance().getDinAlternateBold());
        pbPassword.setTextInputTypeface(FontUtils.getInstance().getDinAlternateBold());
    }

    private void setInputFieldImeListener() {
        pbEmail.setImeActionListener((v, actionId, event) -> {
            pbPassword.requestTheFocus();
            return true;
        });

        pbPassword.setImeActionListener((v, actionId, event) -> {
            KeyboardUtils.forceCloseKeyboard(pbPassword);
            return true;
        });
    }

    private void setInputFieldTextWatcher() {

        pbEmail.setTextWatcher(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                pbEmail.resetError();
                pbPassword.resetError();
                mPresenter.checkValidated(pbEmail.getText(), pbPassword.getText(), false);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        pbPassword.setTextWatcher(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                pbPassword.resetError();
                pbEmail.resetError();
                mPresenter.checkValidated(pbEmail.getText(), pbPassword.getText(), false);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }

    @Override
    public void setPresenter(LoginContract.Presenter presenter) {
        if (presenter != null) {
            this.mPresenter = presenter;
        } else {
            throw new RuntimeException();
        }
    }

    @Override
    public void goBack() {
        onBackPressed();
    }

    @Override
    public void showLoader(String text) {
        if (!skipLoginPressed) {
            btnLogin.startMorphAnimation();
        } else {
            loadingDialog = new LoadingDialog("Creating your guest account", this);
            loadingDialog.show();
        }
    }

    @Override
    public void hideLoader() {
        if (skipLoginPressed) {
            if (loadingDialog != null && loadingDialog.isShowing() && !isFinishing()) {
                loadingDialog.dismiss();
            }
        } else {
            btnLogin.revertAnimation(() -> null);
        }
    }

    @Override
    public void onUnknownError(String error) {
        if (!isFinishing()) {
            try {
                showSingleButtonDialog(getString(R.string.error), error, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void showSingleButtonDialog(String string, String error, DialogInterface.OnDismissListener listener) {
        if (!isFinishing()) {
            DialogUtils.showSingleButtonDialog(string, error, this, listener);
        }
    }

    @Override
    public void onTimeout() {
        showSingleButtonDialog(getString(R.string.timeout_title), getString(R.string.timeout_body), null);
    }

    @Override
    public void onNetworkError() {
        showSingleButtonDialog(getString(R.string.network_error_title), getString(R.string.network_error_body), null);
    }

    @Override
    public void onConnectionError() {
        AnimUtils.slideInTop(llNoInternetHeader, 300, new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                llNoInternetHeader.setVisibility(View.VISIBLE);
                hideNoInternetHeader();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        }, new AccelerateInterpolator());
    }

    @Override
    public void logoutUser() {
        //Not needed
    }

    @Override
    public boolean checkConnection() {
        return ConnectionUtils.userHasConnection(this);
    }

    @Override
    public void startForgotPasswordActivity(String email) {
        Intent forgotPasswordIntent = new Intent(this, ForgotPasswordActivity.class);
        startActivity(forgotPasswordIntent);
        overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_left);
    }

    @Override
    public void startHomeActivity() {
        Intent homeIntent = new Intent(LoginActivity.this, HomeActivity.class);
        startActivity(homeIntent);
        finish();
        overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_left);

    }

    @Override
    public void startSignUpActivity(String email) {
        Intent signUpIntent = new Intent(this, SignUpActivity.class);
        signUpIntent.putExtra(ActivityExtraTags.STRING_USER_EMAIL, pbEmail.getText());
        signUpIntent.putExtra(ActivityExtraTags.BOOL_FROM_LOGIN, true);
        startActivity(signUpIntent);
        finish();
        overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_left);
    }

    private void startWalkthroughActivity() {
        Intent intent = new Intent(this, WalkthroughActivity.class);
        startActivity(intent);
        finish();
        overridePendingTransition(R.anim.slide_in_from_left_fast, R.anim.slide_out_right);
    }

    @Override
    public void showEmailError(String message) {
        pbEmail.showError(message);
    }

    @Override
    public void showPasswordError(String message) {
        pbPassword.showError(message);
    }

    @Override
    public void enableButton() {
        btnLogin.setAlpha(1.0f);
    }

    @Override
    public void disableLoginButton() {
        btnLogin.setAlpha(0.2f);
    }

    @Override
    public String getStringFromResource(int resourceId) {
        return getString(resourceId);
    }

    private void hideNoInternetHeader() {
        new Handler().postDelayed(() -> {
            AnimUtils.slideOutTop(llNoInternetHeader, 300, new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                    llNoInternetHeader.setVisibility(View.INVISIBLE);
                }

                @Override
                public void onAnimationEnd(Animation animation) {

                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
        }, 3000);
    }

    @Override
    public void showDeviceLimitDialog(List<Device> deviceList) {
        if (!isFinishing()) {
            DialogUtils.showDeviceLimitDialog(this, new TwoButtonDialogListener() {
                @Override
                public void onYesClicked() {
                    Intent intent = new Intent(LoginActivity.this, DevicesActivity.class);
                    intent.putExtra("DEVICES", Parcels.wrap(deviceList));
                    startActivityForResult(intent, ActivityRequestCodes.UNLINK_DEVICE_REQUEST_CODE);
                    overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_left);
                }

                @Override
                public void onNoClicked() {
                }
            });
        }
    }

    @Override
    public void showSingleButtonDialog(String error, String message) {
        if (!isFinishing()) {
            DialogUtils.showSingleButtonDialog(error, message, this, null);
        }
    }

    @Override
    public void finishLoginActivity() {
        finish();
    }

    @Override
    public void showLoginSuccess() {
        if (btnLogin != null) {
            Bitmap icon = BitmapFactory.decodeResource(getResources(),
                    R.drawable.ic_action_tick);
            btnLogin.doneLoadingAnimation(ContextCompat.getColor(this, R.color.green_switch_on), icon);
        }
    }

    @Override
    public void onBackPressed() {
        if (isFromGuest) {
            finish();
        } else {
            startWalkthroughActivity();
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == ActivityRequestCodes.UNLINK_DEVICE_REQUEST_CODE && resultCode == RESULT_OK) {
            btnLogin.performClick();
        }

    }

}
