use alienfile;

use Config;

# NOTE: you can set ALIEN_NINJA_FROM_SOURCE to force a build from source.

plugin 'Probe::CommandLine' => (
  command => 'ninja',
  args    => [ '--version' ],
  match   => qr/([0-9\.]+)/,
  version => qr/([0-9\.]+)/,
);

share {
  requires 'Path::Tiny';
  requires 'Sort::Versions';
  requires 'Alien::Build::Plugin::Download::GitHub', '0.09';

  # same URL used for both source and binary releases
  # https://github.com/ninja-build/ninja/releases
  my %github_info = (
      github_user => 'ninja-build',
      github_repo => 'ninja',
  );

  my %os_arch_to_binary_release = (
    # ELF 64-bit LSB executable, x86-64
    'linux:x86_64' => { name => 'ninja-linux', format => 'zip', },

    # Mach-O universal binary with 2 architectures:
    # [x86_64:Mach-O 64-bit x86_64 executable]
    # [arm64:Mach-O 64-bit arm64 executable]
    do {
      map { $_ => { name => 'ninja-mac', format => 'zip', } }
        ('darwin:x86_64', 'darwin:aarch64')
    },

    # PE32+ executable (console) x86-64
    'MSWin32:x86_64' => { name => 'ninja-win', format => 'zip', },
  );

  my $os_arch = join ":", ( $^O, meta->prop->{platform}{cpu}{arch}{name} );
  if(exists $os_arch_to_binary_release{$os_arch}
      && !$ENV{ALIEN_NINJA_FROM_SOURCE}) {
    my ($name, $format) = @{ $os_arch_to_binary_release{$os_arch} }{qw(name format)};
    my $binary_release_re = qr/$name\.\Q$format\E/;
    plugin 'Download::GitHub' => (
      %github_info,
      asset        => 1,
      asset_name   => $name,
      asset_format => $format,
      version      => qr/v([0-9\.]+)/,
    );

    my $cmp = sub {
      my($A,$B) = @_;
      Sort::Versions::versioncmp($B,$A);
    };
    meta->around_hook( prefer => sub {
      my $orig  = shift;
      my $build = shift;
      my $data  = $orig->($build, @_);

      # extract version from URL
      for my $file (@{ $data->{list} }) {
        ( $file->{version} ) = $file->{url} =~ m,/v([0-9\.]+)/${binary_release_re}$,;
      }

      # versioncmp
      my @sorted = sort { $cmp->($a->{version}, $b->{version}) } @{ $data->{list} };

      return +{ type => 'list', list => \@sorted };
    });
    patch sub {
      my $bin_dir = Path::Tiny->new('bin');
      $bin_dir->mkpath;

      my $ninja_bin_name = "ninja$Config{_exe}";
      my $ninja_bin = Path::Tiny->new($ninja_bin_name);
      $ninja_bin->move( $bin_dir->child($ninja_bin_name) );
    };
    plugin 'Build::Copy';
    meta->after_hook( build => sub {
      my($build) = @_;
      $build->runtime_prop->{'style'} = 'binary';
    });
  } else {
    # build from source
    plugin 'Download::GitHub' => (
      %github_info,
    );
    plugin 'Build::CMake';
    build [
      ['%{cmake}',
        ( $^O eq 'MSWin32'
        ? qw(
          -DPLATFORM_HAS_UNISTD_HEADER=0
          -DHAVE_FORK=0 -DHAVE_PIPE=0
        ) : () ),
        @{ meta->prop->{plugin_build_cmake}->{args} },
        '%{.install.extract}',
      ],
      '%{make}',
      '%{make} install',
    ];
    meta->after_hook( build => sub {
      my($build) = @_;
      $build->runtime_prop->{'style'} = 'source';
    });
  }

  gather sub {
    my($build) = @_;
    $build->runtime_prop->{command} = 'ninja';
  };

};

sys {
  meta->after_hook( probe => sub {
    my($build) = @_;
    $build->runtime_prop->{'style'} = 'system';
  });
};
