#ifndef StateIntegrity_hpp
#define StateIntegrity_hpp

#include <string>
#include <JuceHeader.h>

class StateIntegrity {
private:
    struct Private { };
    
public:
    static constexpr const size_t SEED_SIZE = 32;
    static constexpr const size_t PRIVATE_KEY_SIZE = 64;
    static constexpr const size_t PUBLIC_KEY_SIZE = 32;
    static constexpr const size_t SIGNATURE_SIZE = 64;
    
    static std::string generateSeed();
    
    using private_key_t = std::array<unsigned char, PRIVATE_KEY_SIZE>;
    using public_key_t = std::array<unsigned char, PUBLIC_KEY_SIZE>;
    
    StateIntegrity(const std::string_view & seed);
    ~StateIntegrity();
    
    std::string sign(const std::string_view & data);
    std::string verify(const std::string_view & data);
    
    void updateKeyTrust(const std::string_view & key, std::optional<bool> trust);
    std::optional<bool> getKeyTrust(const std::string_view & key);
    
    void loadTrustStore(const juce::XmlElement & elem);
    std::unique_ptr<juce::XmlElement> saveTrustStore();
    void clearTrustStore();
    
    class PublicKeyNotTrusted : public std::exception {
    public:
        PublicKeyNotTrusted(const PublicKeyNotTrusted &) = delete;
        PublicKeyNotTrusted(Private, std::string && publicKey, bool isKnown) : publicKey(std::move(publicKey)), isKnown(isKnown) { }
        virtual char const * what() const noexcept { return "StateIntegrity: Signature verification failed"; }
        const std::string getPublicKey() const { return publicKey; }
        const bool getIsKnown() const { return isKnown; }
    private:
        std::string publicKey;
        bool isKnown;
    };
    
    class SignatureVerificationFailed : public std::exception {
    public:
        SignatureVerificationFailed(const SignatureVerificationFailed &) = delete;
        SignatureVerificationFailed(Private) { };
        virtual char const * what() const noexcept { return "StateIntegrity: Signature verification failed"; }
    };
    
private:
    private_key_t privateKey;
    public_key_t publicKey;
    std::map<public_key_t, bool> trustStore;
};

#endif /* StateIntegrity_hpp */
