package info.knacki.pass.ui;

import android.Manifest;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
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.FileUtils;
import info.knacki.pass.io.IFileInterface;
import info.knacki.gitdroid.callback.OnResponseListener;
import info.knacki.pass.io.PathUtils;
import info.knacki.pass.settings.SettingsManager;
import info.knacki.pass.settings.ui.SettingsActivity;
import info.knacki.pass.ui.alertPrompt.AlertPromptGenerator;
import info.knacki.pass.ui.alertPrompt.views.SimpleTextEdit;
import info.knacki.pass.ui.alertPrompt.views.TextEditAndCheckbox;
import info.knacki.pass.ui.alertPrompt.views.TextView;
import info.knacki.pass.ui.passwordList.EditablePasswordListView;
import info.knacki.pass.ui.passwordList.PasswordEditListener;
import info.knacki.pass.ui.passwordPicker.PasswordPickerFactory;

public class MainActivity extends AppCompatActivity implements PasswordEditListener {
    private final Logger log = Logger.getLogger(MainActivity.class.getName());
    private EditablePasswordListView fPasswordListView;

    protected TextEditAndCheckbox fLastFileName = null;

    protected void CreateNewFolder() {
        AlertPromptGenerator.StaticMake(this)
                .setCancelable(true)
                .setView(new SimpleTextEdit(this))
                .setPositiveButton(R.string.add, (dialogInterface, view) -> {
                    final String filename = ((SimpleTextEdit) view).getStr();

                    if (filename.length() == 0) {
                        Toast.makeText(MainActivity.this, "Error: Empty file name", Toast.LENGTH_LONG).show();
                        return;
                    }
                    File f = new File(fPasswordListView.fCurrentDir +"/" +filename);
                    if (!f.mkdir()) {
                        Toast.makeText(MainActivity.this, "Error: cannot create folder", Toast.LENGTH_LONG).show();
                    }
                    fPasswordListView.refresh();
                })
                .setNegativeButton(R.string.cancel, null)
                .setTitle(R.string.add_title)
                .show();
    }

    protected void CreateNewPassword() {
        if (fLastFileName == null) {
            fLastFileName = new TextEditAndCheckbox(this);
        }
        AlertPromptGenerator.StaticMake(this)
                .setCancelable(true)
                .setView(new TextEditAndCheckbox(this)
                    .setText(fLastFileName.getStr())
                    .setCheckboxCaption(R.string.add_generate)
                    .setChecked(fLastFileName.isChecked()))
                .setPositiveButton(R.string.add, (dialogInterface, view) -> {
                    fLastFileName = (TextEditAndCheckbox) view;
                    final String filename = fLastFileName.getStr();
                    if (filename.length() == 0) {
                        Toast.makeText(MainActivity.this, "Error: Empty file name", Toast.LENGTH_LONG).show();
                        return;
                    }
                    File f = new File(fPasswordListView.fCurrentDir +"/" +filename +FileInterfaceFactory.GetExtension(SettingsManager.GetDefaultEncryptionType(MainActivity.this)));
                    try {
                        FileUtils.Touch(f);
                        fPasswordListView.refresh();
                    }
                    catch (IOException e) {
                        Toast.makeText(MainActivity.this, "Error: " +e.getMessage(), Toast.LENGTH_LONG).show();
                        log.log(Level.WARNING, e.getMessage(), e);
                        return;
                    }
                    if (fLastFileName.isChecked()) {
                        GeneratePassword(f, true);
                    } else {
                        EditFile(f, true);
                    }
                    fLastFileName = null;
                })
                .setNegativeButton(R.string.cancel, (dialogInterface, s) -> dialogInterface.cancel())
                .setTitle(R.string.add_title)
                .show();
    }

    void requestPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        fPasswordListView.refresh();
    }

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

        setTitle(R.string.title);
        fPasswordListView = findViewById(R.id.password_list);
        fPasswordListView.Init(this, PathUtils.GetPassDir(this), false);

        requestPermissions();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case 0:
                break;
            case R.id.id_sync:
                GitPullActivity.StartSyncActivity(this);
                break;
            case R.id.new_folder:
                CreateNewFolder();
                break;
            case R.id.new_password:
                CreateNewPassword();
                break;
            case R.id.settings:
                ShowSettings();
                break;
            case R.id.trash:
                boolean checked = !item.isChecked();
                item.setChecked(checked);
                fPasswordListView.SetDisplayHiddenFiles(checked);
            default:
                log.log(Level.WARNING, "Error: Unknown MenuItem id: " +item.getItemId());
                return false;
        }
        return true;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        if (SettingsManager.GetVCS(this) == null) {
            // Disable sync option
            menu.removeItem(R.id.id_sync);
        }
        return super.onCreateOptionsMenu(menu);
    }

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

        AlertPromptGenerator.StaticMake(this)
            .setCancelable(true)
            .setView(wiz)
            .setPositiveButton(R.string.add, (dialogInterface, view) -> {
                IFileInterface writer = FileInterfaceFactory.GetFileInterface(MainActivity.this, PasswordPickerFactory.GetPasswordPicker(MainActivity.this), f);

                try {
                    writer.WriteFile(PasswordGenerator.generate(wiz), new OnResponseListener<Void>() {
                        @Override
                        public void OnResponse(Void result) {
                        }

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

    protected void EditFile(final File f, boolean editMode) {
        Intent i = new Intent(this, EditPasswordActivity.class);
        i.putExtra(EditPasswordActivity.INTENT_PATH, f.getAbsolutePath());
        i.putExtra(EditPasswordActivity.INTENT_EDIT, editMode);
        startActivity(i);
    }

    protected void ShowSettings() {
        startActivity(new Intent(this, SettingsActivity.class));
    }

    @Override
    public void OnPasswordClicked(File f) {
        EditFile(f, false);
    }

    @Override
    public void OnRemovePassword(File f) {
        AlertPromptGenerator.StaticMake(this)
                .setTitle(R.string.are_you_sure)
                .setView(new TextView(this).SetText(String.format(getString(R.string.about_to_rm_file), f.getName())))
                .setPositiveButton(R.string.ok, (dialogInterface, view) -> {
                    FileUtils.TrashFile(f);
                    fPasswordListView.refresh();
                })
                .setNegativeButton(R.string.cancel, null)
                .show();
        fPasswordListView.refresh();
    }

    private void DoRemoveDir(File f) {
        FileUtils.Rmdir(f);
        fPasswordListView.refresh();
    }

    @Override
    public void OnRemoveDirectory(final File f) {
        if (f.listFiles().length > 0) {
            AlertPromptGenerator.StaticMake(this)
                    .setTitle(R.string.are_you_sure)
                    .setView(new TextView(this)
                            .SetText(R.string.about_to_rm_directory))
                    .setPositiveButton(R.string.ok, (dialogInterface, view) -> DoRemoveDir(f))
                    .setNegativeButton(R.string.cancel, null)
                    .show();

        } else {
            DoRemoveDir(f);
        }
    }

    @Override
    public void OnRestorePassword(File f) {
        FileUtils.RestoreFile(f);
        fPasswordListView.refresh();
    }

    @Override
    public void OnCopyToClipboard(File f) {
        FileInterfaceFactory.GetFileInterface(this, PasswordPickerFactory.GetPasswordPicker(this), f).ReadFile(new OnResponseListener<String>() {
            @Override
            public void OnResponse(String result) {
                ClipboardManager clip = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
                if (clip != null) {
                    clip.setPrimaryClip(ClipData.newPlainText("password", result));
                    Toast.makeText(MainActivity.this, getString(R.string.copied_clipboard), Toast.LENGTH_LONG).show();
                }
            }

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

    @Override
    public void OnEncryptionInformation(File f) {
        Intent i = new Intent(this, EncryptionInformationActivity.class);
        i.putExtra(EncryptionInformationActivity.FILE_PATH, f.getAbsolutePath());
        startActivity(i);
    }

    @Override
    public void onBackPressed() {
        if (!fPasswordListView.ShowParent())
            super.onBackPressed();
    }
}
