#pragma once

#include <array>
#include <filesystem>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>

struct SavedGitCredential
{
    std::string remote_url;
    std::string username;
    std::string password;
};

class UserData
{
public:
    UserData();
    ~UserData();

    [[nodiscard]] const std::filesystem::path &directory() const { return directory_; }
    [[nodiscard]] const std::vector<std::string> &recentRepositories() const { return recent_repositories_; }
    [[nodiscard]] const std::vector<std::string> &recentlyClosed() const { return recently_closed_; }
    [[nodiscard]] const std::vector<std::string> &openRepositories() const { return open_repositories_; }
    [[nodiscard]] size_t activeRepository() const { return active_repository_; }
    [[nodiscard]] float sidebarWidth() const { return sidebar_width_; }
    [[nodiscard]] float detailsWidth() const { return details_width_; }
    [[nodiscard]] float sidebarSectionHeight(size_t index) const { return sidebar_section_heights_.at(index); }
    [[nodiscard]] bool sidebarCollapsed() const { return sidebar_collapsed_; }
    [[nodiscard]] bool sidebarSectionOpen(size_t index) const { return sidebar_section_open_.at(index); }
    [[nodiscard]] float commitTableColumnWidth(size_t index) const { return commit_table_column_widths_.at(index); }
    [[nodiscard]] int pullMode() const { return pull_mode_; }
    [[nodiscard]] int zoomPercent() const { return zoom_percent_; }
    [[nodiscard]] std::optional<SavedGitCredential> remoteCredential(const std::string &remote_url) const;
    static std::string credentialScope(const std::string &remote_url);

    void setSidebarWidth(float width) { sidebar_width_ = width; }
    void setDetailsWidth(float width) { details_width_ = width; }
    void setSidebarSectionHeight(size_t index, float height) { sidebar_section_heights_.at(index) = height; }
    void setSidebarCollapsed(bool collapsed) { sidebar_collapsed_ = collapsed; }
    void setSidebarSectionOpen(size_t index, bool open) { sidebar_section_open_.at(index) = open; }
    void setCommitTableColumnWidth(size_t index, float width) { commit_table_column_widths_.at(index) = width; }
    void setPullMode(int mode)
    {
        pull_mode_ = mode;
        save();
    }
    void setZoomPercent(int percent)
    {
        zoom_percent_ = percent;
        save();
    }
    void addRecentRepository(const std::string &path);
    void addRecentlyClosed(const std::string &path);
    std::string takeRecentlyClosed();
    void setRepositorySession(std::vector<std::string> paths, size_t active_repository);
    void storeRemoteCredential(const std::string &remote_url, const std::string &username,
                               const std::string &password);
    void clearRemoteCredential(const std::string &remote_url);
    void save() const;

private:
    void load();
    [[nodiscard]] std::filesystem::path dataPath() const;
    void removeLegacyFiles() const;

    std::filesystem::path directory_;
    std::vector<std::string> recent_repositories_;
    std::vector<std::string> recently_closed_;
    std::vector<std::string> open_repositories_;
    size_t active_repository_ = 0;
    float sidebar_width_ = 230.0f;
    float details_width_ = 368.0f;
    std::array<float, 4> sidebar_section_heights_ = {110.0f, 220.0f, 90.0f, 150.0f};
    bool sidebar_collapsed_ = false;
    std::array<bool, 4> sidebar_section_open_ = {true, true, true, true};
    std::array<float, 4> commit_table_column_widths_ = {0.0f, 0.0f, 0.0f, 0.0f};
    int pull_mode_ = 1;
    int zoom_percent_ = 100;
    std::unordered_map<std::string, std::string> encrypted_credentials_;
};
