// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use crate::{find_command, workspace_dir};
use flate2::Compression;
use flate2::write::GzEncoder;
use sha2::{Digest, Sha512};
use std::io::BufReader;
use std::io::Read;

mod bump;
mod package;

pub fn update_version() -> anyhow::Result<()> {
    let packages = package::all_packages();
    bump::validate_release_versions(&packages)?;

    let mut updated = false;
    for package in packages {
        updated |= package::update_package_version(&package);
    }
    if !updated {
        println!("all package versions are up-to-date");
    }
    Ok(())
}

pub fn archive_package() -> anyhow::Result<()> {
    std::fs::create_dir_all(workspace_dir().join("dist"))?;

    let workspace_dir = workspace_dir();
    let dist_dir = workspace_dir.join("dist");

    let packages = package::all_packages();
    for package in packages {
        let mut cmd = find_command("git", &workspace_dir);
        cmd.args(["ls-files", "LICENSE", "NOTICE"]);
        cmd.arg(package.name());
        for dep in package.dependencies() {
            cmd.arg(dep.name());
        }
        let output = cmd.output().expect("failed to execute git ls-files");
        let output = String::from_utf8_lossy(&output.stdout);
        let files = output.lines().collect::<Vec<_>>();
        archive_and_checksum(&package, &files)?;

        let filename = format!("{}.tar.gz", package.make_prefix());

        println!("Generate signature for package: {}", package.name());
        let mut cmd = find_command("gpg", &dist_dir);
        cmd.args([
            "--yes",
            "--armor",
            "--output",
            format!("{filename}.asc").as_str(),
            "--detach-sign",
            filename.as_str(),
        ]);
        cmd.output().expect("failed to sign the package");

        println!("Check signature for package: {}", package.name());
        let mut cmd = find_command("gpg", &dist_dir);
        cmd.args([
            "--verify",
            format!("{filename}.asc").as_str(),
            filename.as_str(),
        ]);
        cmd.output()
            .expect("failed to verify the package signature");
    }

    Ok(())
}

fn archive_and_checksum(package: &package::Package, files: &[&str]) -> anyhow::Result<()> {
    println!("Archiving package: {}", package.name());

    let prefix = package.make_prefix();
    let filename = format!("{prefix}.tar.gz");
    let tarball = workspace_dir().join("dist").join(&filename);

    {
        let tarball = std::fs::File::create(&tarball)?;
        let encoder = GzEncoder::new(tarball, Compression::default());
        let mut tar = tar::Builder::new(encoder);
        for file in files {
            tar.append_path_with_name(workspace_dir().join(file), format!("{prefix}/{file}"))?;
        }
    }

    {
        let tarball = std::fs::File::open(&tarball)?;
        let mut reader = BufReader::new(tarball);
        let mut hasher = Sha512::new();
        let mut buf = [0; 8 * 1024];
        loop {
            let n = reader.read(&mut buf)?;
            if n == 0 {
                break;
            }
            hasher.update(&buf[..n]);
        }
        let digest = hasher.finalize();
        let checksum_lines = format!("{}  {filename}", format_digest_hex(digest));

        let checksum = workspace_dir()
            .join("dist")
            .join(format!("{filename}.sha512"));
        std::fs::write(checksum, checksum_lines)?;
    }

    Ok(())
}

fn format_digest_hex(digest: impl AsRef<[u8]>) -> String {
    use std::fmt::Write;

    let digest = digest.as_ref();
    let mut output = String::with_capacity(digest.len() * 2);
    for byte in digest {
        write!(&mut output, "{byte:02x}").expect("writing to String must succeed");
    }
    output
}
