#ifndef CERTINFOEDITOR_HPP
#define CERTINFOEDITOR_HPP

#include "../filezilla/securable_socket.hpp"
#include "../server/server_settings.hpp"

#include <wx/panel.h>

#include "tls_param_editor.hpp"

class wxTextCtrl;
class wxChoicebook;
class wxButton;
class wxBookCtrlBase;
class wxSimplebook;
class wxCheckBox;
class TlsParamEditor;

class CertInfoEditor: public wxPanel
{
public:
	using GenerateSelfsignedFunc = std::function<wxString /*error*/ (const std::string &dn, const std::vector<std::string> &hostnames, fz::tls_param key, fz::native_string password, fz::securable_socket::omni_cert_info &out_cert_info, fz::securable_socket::omni_cert_info::extra &out_extra_info)>;
	using GenerateAcmeFunc = std::function<wxString /*error*/ (const std::vector<std::string> &hostnames, const fz::tls_param &key, const fz::native_string &key_password, fz::securable_socket::omni_cert_info &out_cert_info, fz::securable_socket::omni_cert_info::extra &out_extra_info)>;
	using TestCertificateFunc = std::function<wxString /*error*/ (const fz::securable_socket::cert_info &info, fz::securable_socket::omni_cert_info::extra &out_extra_info)>;
	using SwitchToAcmeOptsFunc = std::function<void ()>;
	using RetrieveDeobfuscatedBlobFunc = TlsParamEditor::RetrieveDeobfuscatedBlobFunc;

	CertInfoEditor() = default;

	bool Create(wxWindow *parent,
				wxWindowID winid = wxID_ANY,
				const wxPoint& pos = wxDefaultPosition,
				const wxSize& size = wxDefaultSize,
				long style = wxTAB_TRAVERSAL | wxNO_BORDER,
				const wxString& name = wxS("certinfoeditor"));

	//! Sets the cert_info data the editor will have to display and let the user edit.
	//! It *doesn't* take ownership of the object.
	void SetValue(fz::securable_socket::cert_info *cert_info, fz::securable_socket::cert_info::extra *extra, fz::util::fs::path_format server_path_format);
	void SetGenerateSelfsignedCertificateFunction(GenerateSelfsignedFunc func);
	void SetGenerateAcmeCertificateFunction(GenerateAcmeFunc func);
	void SetTestCertificateFunction(TestCertificateFunc func);
	void SetRetrieveDeobfuscatedBlobFunction(RetrieveDeobfuscatedBlobFunc func);

	void SetAcmeOptions(const server_settings::acme_options &acme_opts);
	void SetSwitchToAcmeOptsFunc(SwitchToAcmeOptsFunc func);

	bool IsModified();
	bool IsCurrentlyObfuscatedAndNotModified();
	bool SetObfuscatedCert(const fz::securable_socket::cert_info &);

private:
	struct cert_details: wxPanel {
		cert_details(wxWindow *parent);

		void SetValue(const fz::securable_socket::omni_cert_info::extra *);
		void SetWaiting();
		void Clear();

		wxTextCtrl *fingerprint_ctrl_{};
		wxTextCtrl *activation_date_ctrl_{};
		wxTextCtrl *expiration_date_ctrl_{};
		wxTextCtrl *distinguished_name_ctrl_{};
		wxTextCtrl *hostnames_ctrl_{};
	};

	struct cert_form: wxPanel {
		cert_form(wxWindow *parent, bool generate, std::size_t source_id);

		bool SetValue(fz::securable_socket::omni_cert_info *omni, fz::securable_socket::omni_cert_info::extra *extra, fz::util::fs::path_format server_path_format);
		void SetDetails(cert_details *details);
		void SetTestCertificateFunction(TestCertificateFunc func);
		void SetRetrieveDeobfuscatedBlobFunction(RetrieveDeobfuscatedBlobFunc func);
		bool SetGenerating(bool);
		bool IsModified();
		bool IsCurrentlyObfuscatedAndNotModified();
		bool SetObfuscatedCert(const fz::securable_socket::omni_cert_info &);

		TlsParamEditor *certs_ctrl_{};
		TlsParamEditor *key_ctrl_{};
		wxTextCtrl *key_pass_ctrl_{};

		wxButton *generate_ctrl_{};

		fz::securable_socket::omni_cert_info *their_omni_;
		fz::securable_socket::omni_cert_info my_omni_;
		fz::securable_socket::omni_cert_info::extra *their_extra_;
		fz::securable_socket::omni_cert_info::extra my_extra_;
		fz::util::fs::path_format server_path_format_;
		std::size_t source_id_;
		cert_details *details_{};
		TestCertificateFunc test_func_;
		RetrieveDeobfuscatedBlobFunc retrieve_deobfuscated_func_;

		bool certs_modified_{};
		bool key_modified_{};
		bool key_pass_modified_{};
	};

	bool create_acme_editor();

	bool TransferDataFromWindow() override;

	wxChoicebook *book_{};
	wxSimplebook *details_book_{};

	cert_details *provided_details_ctrl_{};
	cert_details *autogenerated_details_ctrl_{};
	cert_details *acme_details_ctrl_{};

	cert_form *provided_generation_{};
	cert_form *autogenerated_generation_{};
	cert_form *acme_generation_{};

	wxWindow *acme_ctrl_{};
	wxWindow *acme_setup_page_{};
	wxWindow *acme_generation_page_{};
	wxCheckBox *autorenew_acme_ctrl_{};

	fz::securable_socket::cert_info *their_cert_info_{};
	fz::securable_socket::cert_info::extra *their_extra_info_{};

	fz::securable_socket::cert_info my_cert_info_{};
	fz::securable_socket::cert_info::extra my_extra_info_{};

	GenerateSelfsignedFunc selfsigned_func_;
	GenerateAcmeFunc acme_func_;

	const server_settings::acme_options *acme_opts_{};
	SwitchToAcmeOptsFunc switch_to_acme_opts_{};
	fz::util::fs::path_format server_path_format_;
};

#endif // CERTINFOEDITOR_HPP
