package org.mercury_im.messenger.ui.account;

import android.os.Bundle;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModelProvider;

import com.google.android.material.textfield.TextInputEditText;

import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.account.error.PasswordError;
import org.mercury_im.messenger.account.error.UsernameError;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.util.Optional;
import org.mercury_im.messenger.util.TextChangedListener;

import butterknife.BindView;
import butterknife.ButterKnife;


/**
 * A login screen that offers login via email/password.
 */
public class LoginActivity extends AppCompatActivity implements TextView.OnEditorActionListener {

    @BindView(R.id.username)
    TextInputEditText addressView;

    @BindView(R.id.password)
    TextInputEditText passwordView;

    @BindView(R.id.sign_in_button)
    Button loginButton;

    private LoginViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_login);
        ButterKnife.bind(this);

        MercuryImApplication.getApplication().getAppComponent().inject(this);

        viewModel = new ViewModelProvider(this).get(LoginViewModel.class);
        observeViewModel();
        setupTextInputListeners();
        loginButton.setOnClickListener(view -> viewModel.login());
    }

    private void observeViewModel() {
        observeUsernameError();
        observePasswordError();
        finishOnceLoginWasSuccessful();
        enableLoginButtonOncePossible();
    }

    private void observeUsernameError() {
        viewModel.getUsernameError().observe(this, usernameError -> {
            addressView.setError(usernameError.isError() ? usernameError.getErrorMessage() : null);
        });
    }

    private void observePasswordError() {
        viewModel.getPasswordError().observe(this, passwordError -> {
            passwordView.setError(passwordError.isError() ? passwordError.getErrorMessage() : null);
        });
    }

    private void finishOnceLoginWasSuccessful() {
        viewModel.isLoginSuccessful().observe(this, successful -> {
            if (Boolean.TRUE.equals(successful)) {
                finish();
            }
        });
    }

    private void enableLoginButtonOncePossible() {
        viewModel.isLoginEnabled().observe(this, isEnabled -> {
            loginButton.setEnabled(isEnabled);
        });
    }

    private Optional<String> getUsernameError(UsernameError usernameError) {
        switch (usernameError) {
            case none:
                return new Optional<>(null);
            case emptyUsername:
                return new Optional<>(getResources().getString(R.string.error_field_required));
            case invalidUsername:
                return new Optional<>(getResources().getString(R.string.error_invalid_username));
            case unknownUsername:
                return  new Optional<>("Unknown Username!");
            default:
                throw new AssertionError("Unknown UsernameError enum value.");
        }
    }

    private Optional<String> getPasswordError(PasswordError passwordError) {
        switch (passwordError) {
            case none:
                return new Optional<>(null);
            case emptyPassword:
                return new Optional<>(getResources().getString(R.string.error_field_required));
            case invalidPassword:
                return new Optional<>(getResources().getString(R.string.error_invalid_password));
            case incorrectPassword:
                return new Optional<>(getResources().getString(R.string.error_incorrect_password));
            default:
                throw new AssertionError("Unknown PasswordError enum value.");
        }
    }

    private void setupTextInputListeners() {
        addressView.setOnEditorActionListener(this);
        passwordView.setOnEditorActionListener(this);

        addressView.addTextChangedListener(new TextChangedListener() {
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                viewModel.setUsername(charSequence.toString());
            }
        });

        passwordView.addTextChangedListener(new TextChangedListener() {
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                viewModel.setPassword(charSequence.toString());
            }
        });
    }

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        switch (v.getId()) {
            case R.id.username:
                if (actionId == EditorInfo.IME_ACTION_NEXT) {
                    passwordView.requestFocus();
                    return true;
                }
                break;

            case R.id.password:
                if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
                    //viewModel.login();
                    return true;
                }
        }
        return false;
    }
}
