use std::{fs, path::PathBuf};

use crate::dirs::{Dirs, DirsError};
use thiserror::Error;

pub struct Lock {
    force: bool,
    lock_file: PathBuf,
}

#[derive(Debug, Error)]
pub enum LockError {
    #[error(transparent)]
    Io(#[from] std::io::Error),
    #[error(transparent)]
    Dirs(#[from] DirsError),
    #[error(transparent)]
    Unknown(#[from] anyhow::Error),
}

impl Lock {
    pub fn new(force: bool) -> Result<Self, LockError> {
        let lock_file = Dirs::get_lock_file()?;

        Ok(Self { lock_file, force })
    }

    pub fn lock() {
        if let Ok(lock_file) = Dirs::get_lock_file() {
            if !fs::exists(&lock_file).unwrap() {
                fs::write(&lock_file, "").expect("there to not be issues with the filesystem");
            }
        }
    }

    pub fn unlock() {
        if let Ok(lock_file) = Dirs::get_lock_file() {
            if fs::exists(&lock_file).unwrap() {
                let _ = fs::remove_file(lock_file);
            }
        }
    }

    pub fn is_locked(&self) -> bool {
        !self.force
            && fs::exists(&self.lock_file).expect("there to not be issues with the filesystem")
    }
}
