package co.pixelbeard.theanfieldwrap.signUp.emailPassword;


import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.rw.keyboardlistener.KeyboardUtils;

import butterknife.BindView;
import butterknife.ButterKnife;
import co.pixelbeard.theanfieldwrap.R;
import co.pixelbeard.theanfieldwrap.customView.PBInputField;
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.signUp.SignUpFragmentListener;
import co.pixelbeard.theanfieldwrap.utils.BaseFragment;
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.utils.ValidationUtils;
import io.realm.Realm;

public class SignUpEmailPasswordFragment extends BaseFragment implements SignUpEmailPasswordContract.View {

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

    @BindView(R.id.pb_email)
    PBInputField pbEmail;
    @BindView(R.id.pb_password)
    PBInputField pbPassword;
    @BindView(R.id.pb_country)
    PBInputField pbCountry;


    private boolean emailAvailable = false;

    private SignUpFragmentListener mListener;
    private Context mContext;

    private SignUpEmailPasswordContract.Presenter mPresenter;

    public SignUpEmailPasswordFragment() {
        // Required empty public constructor
    }

    public static SignUpEmailPasswordFragment newInstance() {
        SignUpEmailPasswordFragment fragment = new SignUpEmailPasswordFragment();
        Bundle args = new Bundle();

        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        mListener = (SignUpFragmentListener) context;
        this.mContext = context;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {

        }

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

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_sign_up_email_password, container, false);
        ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

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

        setupCountryPicker();


        mPresenter.validateFields(pbEmail.getText(), pbPassword.getText(), pbCountry.getText(), false);
    }

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

    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());

        pbCountry.setInputType(InputType.TYPE_CLASS_TEXT);
        pbCountry.setTooltipTypeface(FontUtils.getInstance().getDinAlternateBold());
        pbCountry.setEditTextTypeface(FontUtils.getInstance().getDinAlternateBold());
        pbCountry.setTextInputTypeface(FontUtils.getInstance().getDinAlternateBold());

    }

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

        pbPassword.setImeActionListener((v, actionId, event) -> {
            KeyboardUtils.forceCloseKeyboard(pbPassword);
            new Handler().postDelayed(() -> pbCountry.requestTheFocus(), 100);
            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();
                mPresenter.validateFields(pbEmail.getText(), pbPassword.getText(), pbCountry.getText(), false);
                if (ValidationUtils.isValidEmail(pbEmail.getText())) {
                    mPresenter.checkEmailAvailable(pbEmail.getText());
                }

            }

            @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();
                mPresenter.validateFields(pbEmail.getText(), pbPassword.getText(), pbCountry.getText(), false);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }


    private void setupCountryPicker() {
        pbCountry.getEditText().setShowSoftInputOnFocus(false);
        pbCountry.getEditText().setCursorVisible(false);


        View.OnClickListener listener = v -> showCountriesPicker();

        pbCountry.setOnClickListener(listener);
        pbCountry.getEditText().setOnClickListener(listener);


        pbCountry.getEditText().setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus) {
                showCountriesPicker();
            }
        });


    }

    private void showCountriesPicker() {
        mListener.showCountriesPicker((which, position, valueResult) -> {
            pbCountry.setText(valueResult);
            mPresenter.validateFields(pbEmail.getText(), pbPassword.getText(), pbCountry.getText(), false);
        });
    }


    @Override
    public void isValidated() {

        boolean validated = true;

        if (!mPresenter.validateFields(pbEmail.getText(), pbPassword.getText(), pbCountry.getText(), true) || !emailAvailable) {
            validated = false;
        }


        if (validated && mListener != null) {
            mListener.setEmail(pbEmail.getText());
            mListener.setPassword(pbPassword.getText());
            mListener.setCountry(pbCountry.getText());
            if (mListener.isFromGuest()) {
                mListener.convertGuestToFull();
            } else {
                mListener.registerUser();
            }
        }
    }

    @Override
    public void showInvalidEmailError() {
        if (pbEmail != null && isAdded()) {
            pbEmail.showError(getString(R.string.invalid_email));
        }
    }

    @Override
    public void showEmailNotAvailableError() {
        if (pbEmail != null && isAdded()) {
            pbEmail.showError(getString(R.string.email_unavailable));
        }
    }

    @Override
    public void showPasswordError() {
        if (pbPassword != null && isAdded()) {
            pbPassword.showError(getString(R.string.invalid_password));
        }
    }

    @Override
    public void enableButton() {
        if (emailAvailable && mListener != null && isAdded()) {
            mListener.enableButton();
        }
    }

    @Override
    public void disableButton() {
        if (mListener != null && isAdded()) {
            mListener.disableButton();
        }
    }

    @Override
    public void setEmailAvailable(boolean isAvailable) {
        this.emailAvailable = isAvailable;
        if (isAvailable && mPresenter.validateFields(pbEmail.getText(), pbPassword.getText(), pbCountry.getText(), false)) {
            enableButton();
        } else disableButton();

    }

    @Override
    public void showNoConnectionHeader() {
        if (mListener != null && isAdded()) {
            mListener.showNoInternetHeader();
        }
    }


    @Override
    public void showCountryError() {
        if (pbCountry != null && isAdded()) {
            pbCountry.showError(getString(R.string.invalid_country));
        }
    }

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

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

    @Override
    public void showLoader(String text) {
        //Not needed
    }

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

    @Override
    public void showSingleButtonDialog(String title, String body, DialogInterface.OnDismissListener listener) {
        DialogUtils.showSingleButtonDialog(title, body, mContext, listener);
    }

    @Override
    public void onUnknownError(String error) {
        showSingleButtonDialog(getString(R.string.error), error, null);
    }

    @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() {
        showNoConnectionHeader();
    }

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

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