package info.knacki.pass.input;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.inputmethodservice.InputMethodService;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ScrollView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import info.knacki.pass.R;
import info.knacki.pass.generator.PasswordGenerator;
import info.knacki.pass.generator.ui.PasswordGeneratorWizard;
import info.knacki.pass.io.FileInterfaceFactory;
import info.knacki.pass.io.IFileInterface;
import info.knacki.pass.io.OnResponseListener;
import info.knacki.pass.io.PathUtils;
import info.knacki.pass.settings.SettingsManager;
import info.knacki.pass.ui.MainActivity;
import info.knacki.pass.ui.alertPrompt.ServiceAlertPromptGenerator;
import info.knacki.pass.ui.alertPrompt.views.SimpleTextEditWithKeyboard;
import info.knacki.pass.ui.passwordList.PasswordClickListener;
import info.knacki.pass.ui.passwordList.PasswordListView;
import info.knacki.pass.ui.passwordPicker.PasswordPickerFactory;

public class InputService extends InputMethodService implements PasswordClickListener {
    protected PasswordListView fPasswordListView;
    private static final Logger log = Logger.getLogger(InputService.class.getName());
    protected View fInputView;

    @Override
    public void onStartInputView(EditorInfo info, boolean restarting) {
        super.onStartInputView(info, restarting);
        if (fPasswordListView != null) {
            fPasswordListView.reset();
        }
    }

    @SuppressLint("InflateParams")
    @Override
    public View onCreateInputView() {
        fInputView = LayoutInflater.from(this).inflate(R.layout.input, null, false);
        fPasswordListView = new PasswordListView<>(this, PathUtils.GetPassDir(this));
        ((ScrollView)fInputView.findViewById(R.id.passwordListContainer)).addView(fPasswordListView);
        fInputView.findViewById(R.id.prevButton).setOnClickListener(view -> {
            InputMethodManager service = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            if (null == service) {
                Toast.makeText(InputService.this, "Android error", Toast.LENGTH_LONG).show();
                log.log(Level.SEVERE, "Cannot get Input method service");
                return;
            }
            service.showInputMethodPicker();
        });
        fInputView.findViewById(R.id.backspaceButton).setOnClickListener(view -> getCurrentInputConnection().deleteSurroundingText(1, 0));
        fInputView.findViewById(R.id.generateButton).setOnClickListener(view -> CreatePassword());
        fInputView.findViewById(R.id.openAppButton).setOnClickListener(view -> startActivity(new Intent(InputService.this, MainActivity.class)));
        return fInputView;
    }

    protected void CreatePassword() {
        new ServiceAlertPromptGenerator(fInputView).Generate(this)
                .setCancelable(true)
                .setView(new SimpleTextEditWithKeyboard(this))
                .setPositiveButton(R.string.add, (dialogInterface, view) -> {
                    final String filename = ((SimpleTextEditWithKeyboard) view).getStr();
                    if (filename.length() == 0) {
                        Toast.makeText(InputService.this, "Error: Empty file name", Toast.LENGTH_LONG).show();
                        return;
                    }
                    File f = new File(fPasswordListView.fCurrentDir +"/" +filename +FileInterfaceFactory.GetExtension(SettingsManager.GetDefaultEncryptionType(InputService.this)));
                    try {
                        f.createNewFile();
                        fPasswordListView.refresh();
                    }
                    catch (IOException e) {
                        Toast.makeText(InputService.this, "Error: " +e.getMessage(), Toast.LENGTH_LONG).show();
                        log.log(Level.WARNING, e.getMessage(), e);
                        return;
                    }
                    GeneratePassword(f);
                })
                .setNegativeButton(R.string.cancel, null)
                .setTitle(R.string.add_title)
                .show();
    }

    protected void GeneratePassword(final File f) {
        final PasswordGeneratorWizard wiz = new PasswordGeneratorWizard(this);

        new ServiceAlertPromptGenerator(fInputView).Generate(this)
                .setCancelable(true)
                .setView(wiz)
                .setPositiveButton(R.string.add, (dialogInterface, view) -> {
                    IFileInterface writer = FileInterfaceFactory.GetFileInterface(InputService.this, PasswordPickerFactory.GetPasswordPicker(InputService.this), f);

                    try {
                        final String pwd = PasswordGenerator.generate(wiz);
                        writer.WriteFile(pwd, new OnResponseListener<Void>() {
                            @Override
                            public void OnResponse(Void result) {
                                sendPassword(pwd);
                            }

                            @Override
                            public void OnError(final String msg, final Throwable e) {
                            }
                        });
                    }
                    catch (IFileInterface.InvalidPasswordException e) {
                        f.delete();
                        log.log(Level.WARNING, e.getMessage(), e);
                        Toast.makeText(InputService.this, "Error: " +e.getMessage(), Toast.LENGTH_LONG).show();
                        fPasswordListView.refresh();
                    }
                })
                .setNegativeButton(R.string.cancel, null)
                .setTitle(R.string.generate_title)
                .show();
    }

    public void sendPassword(String passwordContent) {
        getCurrentInputConnection().commitText(passwordContent, passwordContent.length());
        onFinishInput();
    }

    @Override
    public void OnPasswordClicked(File f) {
        FileInterfaceFactory.GetFileInterface(this, PasswordPickerFactory.GetPasswordPicker(this, fInputView), f).ReadFile(new OnResponseListener<String>() {
            @Override
            public void OnResponse(String passwordContent) {
                sendPassword(passwordContent);
            }

            @Override
            public void OnError(String msg, Throwable e) {
                Toast.makeText(InputService.this, "Error: " + msg, Toast.LENGTH_LONG).show();
                log.log(Level.SEVERE, msg, e);
            }
        });
    }
}
