use alienfile;
use Env::ShellWords qw( @LDFLAGS );
use Text::ParseWords qw( shellwords );
use FFI::CheckLib qw( find_lib_or_die );

configure { requires 'Env::ShellWords' => 0; requires 'FFI::CheckLib' => 0 };

plugin 'PkgConfig' => 'libcurl';

plugin 'Probe::CommandLine' => (
  command   => $_,
  secondary => 1,
) for qw( curl-config curl );

meta->around_hook(probe => sub {
  my $orig = shift;
  my $build = shift;

  my $type = $orig->($build,@_);
  if($type eq 'system')
  {
    find_lib_or_die lib => 'curl';
  }
  $type;
});

share {

  my $alien_ssl = 'Alien::OpenSSL';

  my @acflags;

  # - schannel is the native SSL on windows
  if($^O eq 'MSWin32')
  {
    unshift @acflags, '--with-schannel';
    undef $alien_ssl;
  }
  # - libressl is the native SSL on openbsd and would be expected to be used there.
  elsif($^O eq 'openbsd')
  {
    $alien_ssl = 'Alien::LibreSSL';
    unshift @acflags, '--with-openssl';
  }
  # - macOS has its own native SSL implementation which is supported by curl
  elsif($^O eq 'darwin')
  {
    unshift @acflags, '--with-secure-transport';
    undef $alien_ssl;
  }
  # - elsewhere OpenSSL is probably a reasonable option
  else
  {
    unshift @acflags, '--with-openssl';
  }

  if($alien_ssl)
  {
    if($alien_ssl eq 'Alien::OpenSSL')
    {
      requires $alien_ssl => '0.15';
    }
    else
    {
      requires $alien_ssl => 0;
    }

    # Build::SearchDep should have an option to do just this
    # without modifying the build stage
    # https://github.com/PerlAlien/Alien-Build/issues/373
    meta->after_hook(
      gather_share => sub {
        my($build) = @_;
        $build->runtime_prop->{$_} .= $alien_ssl->$_ for qw( libs libs_static cflags cflags_static );
      }
    );
  }

  plugin Download => (
    url     => 'https://curl.haxx.se/download/',
    version => qr/^curl-([0-9\.]+)\.tar\.gz$/,
  );
  plugin Extract => 'tar.gz';

  # make sure that curl uses the linker flags
  # from our Alien SSL
  if($alien_ssl)
  {
    meta->around_hook( $_ => sub {
      my $orig = shift;
      my $build = shift;
      local $ENV{LDFLAGS}  = $ENV{LDFLAGS};
      unshift @LDFLAGS,  grep /^-L/, shellwords( $alien_ssl->libs   );
      log "using LDFLAGS = $ENV{LDFLAGS}";
      $orig->($build, @_);
    }) for qw( build build_ffi );
  }

  plugin 'Build::Autoconf' => ();

  build [
    "%{configure} --disable-shared --enable-static @acflags",
    '%{make}',
    '%{make} install',
  ];

  after gather => sub {
    my $build = shift;
    return unless $alien_ssl;
    $build->install_prop->{libs_static} = join(' ',
      $build->install_prop->{libs_static},
      grep /^-L/,
      shellwords( $alien_ssl->libs ),
    );
  };

  requires 'Path::Tiny';

  my $ffi_target = '%{.install.autoconf_prefix}/dynamic';
  ffi {

    my $patch_makefile = sub {
      my ($build) = @_;
  
      #  should also check curl version as change is not needed from 7.88
      return if $^O ne 'MSWin32';
  
      my $target_file = "src/Makefile";
      $build->log ("Patching $target_file for share build");
      
      my $target_text
        = quotemeta '$(LIBTOOL) --tag=RC --mode=compile $(RC) -I$(top_srcdir)/include';
      my $new_text
        = '$(RC) -I$(top_srcdir)/include';
  
      Path::Tiny->new($target_file)->edit_raw(sub {s/^(\s+)$target_text/$1$new_text/ms});
  
      return;
    };

    build [
      "%{configure} --enable-shared --disable-static --bindir=$ffi_target --libdir=$ffi_target @acflags",
      $patch_makefile,
      '%{make}',
      '%{make} install',
      sub {
        my $build = shift;
        return unless $^O eq 'MSWin32';
        my $root = Path::Tiny->new($ENV{DESTDIR})->child($build->install_prop->{autoconf_prefix});
        log "re-routing DLLs in $root";
        foreach my $from (grep /\.dll$/i, $root->child('bin')->children)
        {
          my $to = $root->child('dynamic', $from->basename);
          log "move $from => $to";
          $from->move($to);
        }
      },
    ];
  };

};