#!/usr/bin/env raku

use File::Temp;
use Config::Clever;
use Cro::HTTP::Client;
use JSON::Fast;

use Module2Rpm::Download::Git;
use Module2Rpm::Archive::Tar;
use Module2Rpm::Spec;
use Module2Rpm::Package;
use Module2Rpm::Helper;
use Module2Rpm::Upload::OBS;
use Module2Rpm::Cro::Client;

my $helper = Module2Rpm::Helper.new;

# Place where all source archives and spec files will be saved before uploading.
my $destination-path = tempdir().IO;

# Load config from home folder: HOME/.config/module2rpm/default.json
my $config-dir = $*HOME.add('.config');
$config-dir.mkdir unless $config-dir.e;
$config-dir .= add('module2rpm');
$config-dir.mkdir unless $config-dir.e;

my $config-file = $config-dir.add('default.json');
unless $config-file.e {
    say "Config does not exists. Create $config-file";
    my %new-config;
    %new-config<obs-user> = prompt "Enter OBS user: ";
    %new-config<obs-password> = prompt "Enter OBS password: ";
    %new-config<obs-project> = prompt "Enter OBS project: ";

    $config-file.spurt(to-json(%new-config));
}

say "Load config: $config-dir";
my %config = Config::Clever.load(config-dir => $config-dir);
# Config for Open Build Service.
# User using the OBS API: https://api.opensuse.org
my $obs-user = %config<obs-user>;
# Password for the OBS user:
my $obs-password = %config<obs-password>;
# Project to upload the modules to:
my $obs-project = %config<obs-project>;

my $client = Module2Rpm::Cro::Client.new(auth => {
    username => $obs-user,
    password => $obs-password
});

#| Prints the help.
multi MAIN(:h(:$help)) {
    help();
}

#| Downloads, creates spec files and uploads them to OBS for all modules given in a file.
multi MAIN(:$file!) {
    say "Parse download file: $file";
    my @packages = $helper.create-packages(path => $destination-path, file => $file.IO);

    for @packages -> $package {
        say "{$package.spec.get-name()}: Download source...";
        $package.Download();
        say "{$package.spec.get-name()}: Write spec file...";
        $package.write-spec-file();

        my $obs = Module2Rpm::Upload::OBS.new(client => $client, project => $obs-project);
        say "Upload {$package.spec.get-name()} to OBS";
        $obs.upload-files(package => $package);
    }
}

#| Downloads, creates spec file and uploads to OBS a given module.
multi MAIN(:$module!) {
    say "Fetch module metadata...";
    my %all-metadata = $helper.fetch-metadata();

    my $module-metadata = %all-metadata{$module};
    die "Did not find metadata for module '$module'" unless $module-metadata;

    my $spec = Module2Rpm::Spec.new(metadata => $module-metadata);
    my $package = Module2Rpm::Package.new(spec => $spec, path => $destination-path);

    say "Download module source...";
    $package.Download();

    say "Write spec file...";
    $package.write-spec-file();

    my $obs = Module2Rpm::Upload::OBS.new(client => $client, project => $obs-project);
    say "Upload module to OBS";
    $obs.upload-files(package => $package);

    say "Done";
}

sub help() {
    say q:to/HELP/;
    module2rpm [--module=module::name | --file=filePath]

    This program downloads the source of a Raku module, writes the spec file
    with the metadata and uploads both files to OBS.

    OPTIONS:
        --module=module::name   Looks for the module::name in the Raku
                                ecosystem to get the metadata of it. Then write
                                the spec file and uploads the module source and
                                spec file to OBS.
        --file=filePath         Expect a file with either Module::Names or
                                metadata urls. Download the sources and
                                uploaded them together with the spec files to
                                OBS.
    HELP
}
