package it.niedermann.nextcloud.deck.ui;

import android.os.Bundle;
import android.text.Editable;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider;

import com.nextcloud.android.sso.api.EmptyResponse;

import it.niedermann.android.reactivelivedata.ReactiveLiveData;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityPickStackBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Board;
import it.niedermann.nextcloud.deck.model.Stack;
import it.niedermann.nextcloud.deck.remote.api.IResponseCallback;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackFragment;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackListener;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackViewModel;
import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
import it.niedermann.nextcloud.deck.ui.theme.Themed;
import it.niedermann.nextcloud.deck.util.OnTextChangedWatcher;
import okhttp3.Headers;

public abstract class PickStackActivity extends AppCompatActivity implements Themed, PickStackListener {

    private ActivityPickStackBinding binding;
    private PickStackViewModel viewModel;

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

        Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));

        binding = ActivityPickStackBinding.inflate(getLayoutInflater());
        viewModel = new ViewModelProvider(this).get(PickStackViewModel.class);

        setContentView(binding.getRoot());
        setSupportActionBar(binding.toolbar);

        final var hasAccounts$ = new ReactiveLiveData<>(viewModel.hasAccounts());

        hasAccounts$
                .filter(hasAccounts -> !hasAccounts)
                .observe(this, () -> startActivity(ImportAccountActivity.createIntent(this)));

        hasAccounts$
                .filter(hasAccounts -> hasAccounts)
                .observe(this, () -> getSupportFragmentManager()
                        .beginTransaction()
                        .replace(R.id.fragment_container, PickStackFragment.newInstance(showBoardsWithoutEditPermission()))
                        .commit());

        binding.cancel.setOnClickListener((v) -> finish());
        binding.submit.setOnClickListener((v) -> {
            viewModel.setSubmitInProgress(true);
            onSubmit(viewModel.getAccount(), viewModel.getBoardLocalId(), viewModel.getStackLocalId(), new IResponseCallback<>() {
                @Override
                public void onResponse(EmptyResponse response, Headers headers) {
                    runOnUiThread(() -> viewModel.setSubmitInProgress(false));
                }

                @Override
                public void onError(Throwable throwable) {
                    IResponseCallback.super.onError(throwable);
                    runOnUiThread(() -> {
                        viewModel.setSubmitInProgress(false);
                        ExceptionDialogFragment
                                .newInstance(throwable, viewModel.getAccount())
                                .show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
                    });
                }
            });
        });
        viewModel.submitButtonEnabled().observe(this, enabled -> binding.submit.setEnabled(enabled));
        if (requireContent()) {
            viewModel.setContentIsSatisfied(false);
            binding.inputWrapper.setVisibility(View.VISIBLE);
            binding.input.addTextChangedListener(new OnTextChangedWatcher(s -> viewModel.setContentIsSatisfied(s != null && !s.trim().isEmpty())));
        } else {
            viewModel.setContentIsSatisfied(true);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.binding = null;
    }

    @Override
    public void onStackPicked(@NonNull Account account, @Nullable Board board, @Nullable Stack stack) {
        viewModel.setSelected(account, board, stack);
        applyTheme(board == null
                ? ContextCompat.getColor(this, R.color.onSurface)
                : board.getColor()
        );
    }

    @Override
    public void applyTheme(int color) {
        final var utils = ThemeUtils.of(color, this);

        utils.material.themeToolbar(binding.toolbar);
        utils.deck.themeStatusBar(this, binding.appBarLayout);
        utils.material.colorMaterialButtonText(binding.cancel);
        utils.material.colorMaterialButtonPrimaryFilled(binding.submit);
        utils.material.colorTextInputLayout(binding.inputWrapper);
    }

    abstract protected void onSubmit(Account account, long boardLocalId, long stackId, @NonNull IResponseCallback<EmptyResponse> callback);

    abstract protected boolean showBoardsWithoutEditPermission();

    protected boolean requireContent() {
        return false;
    }

    @NonNull
    protected String getContent() {
        final Editable text = binding.input.getText();
        return text == null ? "" : text.toString();
    }
}