use alienfile;
use Path::Tiny qw( path );
use Capture::Tiny qw( capture );
use Config;

configure {
  requires 'Path::Tiny';
  requires 'Capture::Tiny';
};

probe sub {
  my($build) = @_;

  foreach my $command (qw( m4 gm4 gnum4 ), $ENV{M4})
  {
    my @stdout;
    capture { @stdout = `$command --version` };
    if(defined $stdout[0] && $stdout[0] =~ /^(GNU |)m4/i && $stdout[0] =~ /([0-9]+\.[0-9]+\.[0-9]+)/)
    {
      my $version = $1;
      my @version = split /\./, $version;

      # GNU M4 seems to have a history of brokenness
      # so says AutoConf:
      # GNU M4 1.4.6 or later is required; 1.4.16 or newer is recommended.
      # GNU M4 1.4.15 uses a buggy replacement strstr on some systems.
      # Glibc 2.9 - 2.12 and GNU M4 1.4.11 - 1.4.15 have another strstr bug.

      return 'share' unless $version[0] >= 1;

      if($version[0] == 1)
      {
        return 'share' unless $version[1] >= 4;

        if($version[1] == 4)
        {
          return 'share' unless $version[2] >= 6;
          return 'share' if $version[2] =~ /^(11|12|13|14|15)$/;
        }
      }

      $build->install_prop->{my_version} = $version;
      $build->install_prop->{my_command} = $command;

      return 'system';
    }
  }

  if($^O eq 'MSWin32')
  {
    path('test1.c')->spew(
      "#define __USE_MINGW_ANSI_STDIO 1\n",
      "#include <stdio.h>\n",
      "int asprintf(char **__ret, const char *__format, ...) { return 0; }\n",
    );
    my(undef, $ret) = capture {
      system $Config{cc}, '-std=gnu99', -c => 'test1.c', -o => 'test1.o';
      $?;
    };
    if($ret)
    {
      log('need to patch lib/asprintf.c');
      $build->install_prop->{my_patch_asprintf} = 1;
    }
  }

  return 'share';
};

share {

  plugin 'Download' => (
    url     => 'https://ftp.gnu.org/gnu/m4',
    version => qr/m4-([0-9\.]+)\.tar\.gz/,
  );

  plugin 'Extract' => 'tar.gz';

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

  if($^O eq 'MSWin32')
  {
    plugin 'Prefer::BadVersion' => '1.4.19';
    patch sub {
      my($build) = @_;

      # workaround: m4 has its own implementation of asprintf
      # and so does mingw.  The latter is defined as an inline
      # function in stdio.h which conflicts at least on some
      # older versions of the mingw runtime, or gcc.  This
      # makes the asprintf.c empty so that it will build cleanly
      # when that happened.  Observed with the mingw that comes
      # with AS perl 5.24.  I may have also seen it from cpantesters
      # from a probable strawberry Perl
      if($build->install_prop->{my_patch_asprintf})
      {
        $build->log('patching lib/asprintf.c');
        path('lib/asprintf.c')->spew('');
      }
    };
  }
  elsif($^O eq 'linux')
  {
    #patch [
    #  # this is the patch that Debian applies
    #  '%{patch} -p1 < %{.install.patch}/01-fix-ftbfs-with-glibc-2.28.patch',
    #];
  }
  elsif($^O eq 'darwin')
  {
    plugin 'Prefer::BadVersion' => '1.4.19';
    patch [
      # this is the patch that homebrew applies
      '%{patch} -p0 < %{.install.patch}/secure_snprintf.patch',
    ];
  }

  gather sub {
    my($build) = @_;
    my @stdout;
    capture { @stdout = `m4 --version` };
    $build->runtime_prop->{version} =
      defined $stdout[0] && $stdout[0] =~ /^m4/ && $stdout[0] =~ /([0-9\.]+)$/
        ? $1
        : 'unknown';
  };

};

sys {

  gather sub {
    my($build) = @_;

    $build->runtime_prop->{$_} = $build->install_prop->{"my_$_"} for qw( version command );
  };

};
