use std::path::PathBuf;

use clap::Clap;
use libpijul::change::Local;
use libpijul::changestore::ChangeStore;
use libpijul::*;

use crate::repository::*;

#[derive(Clap, Debug)]
pub struct Change {
    /// Use the repository at PATH instead of the current directory
    #[clap(long = "repository", value_name = "PATH")]
    repo_path: Option<PathBuf>,
    /// The hash of the change to show, or an unambiguous prefix thereof
    #[clap(value_name = "HASH")]
    hash: Option<String>,
}

impl Change {
    pub fn run(self) -> Result<(), anyhow::Error> {
        let repo = Repository::find_root(self.repo_path.clone())?;
        let txn = repo.pristine.txn_begin()?;
        let changes = repo.changes;

        let hash = if let Some(hash) = self.hash {
            txn.hash_from_prefix(&hash)?.0
        } else {
            let channel_name = repo.config.get_current_channel(None);
            let channel = if let Some(channel) = txn.load_channel(channel_name)? {
                channel
            } else {
                return Ok(());
            };
            let channel = channel.borrow();
            if let Some(h) = txn.reverse_log(&channel, None)?.next() {
                (h?.1).0
            } else {
                return Ok(());
            }
        };
        let change = changes.get_change(&hash).unwrap();
        let file_name = |l: &Local, _| format!("{}:{}", l.path, l.line);
        let o = std::io::stdout();
        let mut o = o.lock();
        super::pager();
        change.write(&changes, Some(hash), file_name, true, &mut o)?;
        Ok(())
    }
}