use serde::{Deserialize, Serialize};

/// Repository collaborator role. Stored as `"read"`, `"write"`, or `"admin"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum CollabRole {
    Read,
    Write,
    Admin,
}

impl std::fmt::Display for CollabRole {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            CollabRole::Read => write!(f, "read"),
            CollabRole::Write => write!(f, "write"),
            CollabRole::Admin => write!(f, "admin"),
        }
    }
}

impl std::str::FromStr for CollabRole {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "read" => Ok(CollabRole::Read),
            "write" => Ok(CollabRole::Write),
            "admin" => Ok(CollabRole::Admin),
            _ => Err("unknown collaborator role"),
        }
    }
}

/// LFS lock type. Stored as `"rd"`, `"rn"` or `"rw"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum LockType {
    Rd,
    Rn,
    Rw,
}

impl std::fmt::Display for LockType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            LockType::Rd => write!(f, "rd"),
            LockType::Rn => write!(f, "rn"),
            LockType::Rw => write!(f, "rw"),
        }
    }
}

impl std::str::FromStr for LockType {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "rd" => Ok(LockType::Rd),
            "rn" => Ok(LockType::Rn),
            "rw" => Ok(LockType::Rw),
            _ => Err("unknown lock type"),
        }
    }
}

/// Upstream sync direction. Stored as `"push"` or `"pull"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum SyncDirection {
    Push,
    Pull,
}

impl std::fmt::Display for SyncDirection {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            SyncDirection::Push => write!(f, "push"),
            SyncDirection::Pull => write!(f, "pull"),
        }
    }
}

impl std::str::FromStr for SyncDirection {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "push" => Ok(SyncDirection::Push),
            "pull" => Ok(SyncDirection::Pull),
            _ => Err("unknown sync direction"),
        }
    }
}

/// Upstream sync status.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum SyncStatus {
    Idle,
    Syncing,
    Success,
    Failed,
}

impl std::fmt::Display for SyncStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            SyncStatus::Idle => write!(f, "idle"),
            SyncStatus::Syncing => write!(f, "syncing"),
            SyncStatus::Success => write!(f, "success"),
            SyncStatus::Failed => write!(f, "failed"),
        }
    }
}

impl std::str::FromStr for SyncStatus {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "idle" => Ok(SyncStatus::Idle),
            "syncing" => Ok(SyncStatus::Syncing),
            "success" => Ok(SyncStatus::Success),
            "failed" => Ok(SyncStatus::Failed),
            _ => Err("unknown sync status"),
        }
    }
}

pub use repo::Entity as Repo;
pub use repo_branch::Entity as RepoBranch;
pub use repo_branch_protect::Entity as RepoBranchProtect;
pub use repo_collaborator::Entity as RepoCollaborator;
pub use repo_commit::Entity as RepoCommit;
pub use repo_fork::Entity as RepoFork;
pub use repo_history_name::Entity as RepoHistoryName;
pub use repo_hook::Entity as RepoHook;
pub use repo_lfs_lock::Entity as RepoLfsLock;
pub use repo_lfs_object::Entity as RepoLfsObject;
pub use repo_lock::Entity as RepoLock;
pub use repo_star::Entity as RepoStar;
pub use repo_tag::Entity as RepoTag;
pub use repo_upstream::Entity as RepoUpstream;
pub use repo_watch::Entity as RepoWatch;
pub use repo_webhook::Entity as RepoWebhook;

pub mod repo;
pub mod repo_branch;
pub mod repo_branch_protect;
pub mod repo_collaborator;
pub mod repo_commit;
pub mod repo_fork;
pub mod repo_history_name;
pub mod repo_hook;
pub mod repo_lfs_lock;
pub mod repo_lfs_object;
pub mod repo_lock;
pub mod repo_star;
pub mod repo_tag;
pub mod repo_upstream;
pub mod repo_watch;
pub mod repo_webhook;
