The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# Note: I'm sure this won't work on Windows.
# First of all, I don't think pkg-config gets installed on Windows,
# but you can try setting the environment variables.
# Then you're going to have to compile it using, what, nmake?
# Let me know how to do it if you get it installed.

use strict;
use warnings;
use Config;
use ExtUtils::MakeMaker;
use File::Spec;

main();
exit 0;

sub main {
    my $fixed_args = fixed_args();
    my $varied_args = varied_args();
    my $gpp_warn_args = gpp_warn_args();

    WriteMakefile(%$fixed_args, %$varied_args, %$gpp_warn_args);
}

sub gpp_warn_args {
    # If you're using gcc >= 4.2, you'll probably
    # get warnings like this during `make` :
    #  OIS.c:1835: warning: deprecated conversion from string constant to 'char*'
    # The C code generated by `xsubpp` uses literal strings (string constants)
    # as args to functions expecting char*. This disables those warnings....

    if (my_compiler() eq 'g++') {
        my $str = `g++ -dumpversion`;
        unless ($?) {
            chomp $str;
            my ($v, $s) = split /\./, $str;
            if (($v == 4 && $s >= 2) || $v > 4) {
                return {'CCFLAGS' => '-Wno-write-strings'};
            }
        }
    }

    # there will be no warnings, or we'll just tolerate them
    return {};
}

sub my_compiler {
    return $ENV{'CXX'} || 'g++';
}

sub fixed_args {
    my ($pkg) = @_;

    return {
        'NAME'          => 'Ogre::AL',
        'VERSION_FROM'  => 'lib/Ogre/AL.pm',
        'AUTHOR'        => 'Scott Lanning <slanning@cpan.org>',
        'LD'            => '$(CC)',
        'OBJECT'        => '$(O_FILES)',
        'MAN3PODS'      => {},
        'XSOPT'         => '-C++',
    };
}

sub varied_args {
    my ($been_there) = @_;
    my (@cflags, @libs);

    # Find out if OgreAL is installed

    # any env vars take priority
    if (ogreal_envvars_set()) {
        push @cflags, $ENV{OGREAL_CFLAGS};
        push @libs, $ENV{OGREAL_LIBS};

        push @cflags, $ENV{OPENAL_CFLAGS};
        push @libs, $ENV{OPENAL_LIBS};
    }
    # otherwise try to find info with pkg-config
    elsif (pkgconfig_found('OgreAL', '0.2.5') && pkgconfig_found('openal', '1.1.0')) {
        push @cflags, pkg_config('OgreAL', 'cflags');
        push @libs, pkg_config('OgreAL', 'libs');

        push @cflags, pkg_config('openal', 'cflags');
        push @libs, pkg_config('openal', 'libs');
    }

    else {
        if (defined $been_there) {
            error("OgreAL and/or libopenal CFLAGS and LIBS not found, so giving up.",
                  "Be sure to read README.txt!");
        }
        else {
            # give them a chance
            where_am_i();
            # recursion, tricky... it's just to rerun things now that
            # we got the env vars
            return varied_args('got the t-shirt');
        }
    }

    my @defines = ();   # (not used for now)

    my %prereqs = (
        'Test::More' => 0,
        'Ogre' => 0.35,
    );


    # Check if optional Perl modules are installed.

    my $OIS_REQ_VERSION = 0.04;
    unless (eval { require OIS && $OIS::VERSION >= $OIS_REQ_VERSION }) {
        my $msg = "\nNote: the Perl module OIS >= $OIS_REQ_VERSION is not installed,\n"
          . "so you won't be able to run some examples\n"
          . "or use Ogre::ExampleFrameListener.\n"
          . "Installing OIS would be a very good idea\n"
          . "unless you have some other way to handle keyboard and mouse input.\n"
          . "It's fine to install it after installing OgreAL.\n\n"
          . "Do you want to install OIS now?";

        my $val = ExtUtils::MakeMaker::prompt($msg, 'n');
        if ($val =~ /^y/i) {
            $prereqs{'OIS'} = $OIS_REQ_VERSION;
            print "\nOIS >= $OIS_REQ_VERSION added to prerequisites.\n";
        }
    }


    return {
        'PREREQ_PM'         => \%prereqs,
        'CC'                => my_compiler(),
        'INC'               => join(' ', @cflags),
        'LIBS'              => join(' ', @libs),
        (@defines ? ('DEFINE' => join(' ', @defines)) : ()),
    };
}

sub ogreal_envvars_set {
    return exists $ENV{OGREAL_CFLAGS} && exists $ENV{OGREAL_LIBS}
      && exists $ENV{OPENAL_CFLAGS} && exists $ENV{OPENAL_LIBS}
}

sub pkgconfig_found {
    my ($pkgname, $version, $fatal) = @_;

    unless (pkg_config_installed()) {
        error("pkg-config not found") if defined $fatal;
    }

    my @errors = check_pkg_config($pkgname, $version);
    error(@errors) if defined $fatal;

    return !@errors;
}

# check out the love, man
sub where_am_i {
    REDO: {
        my $msg = "\nI can't get no.... satisfaction, but I tried... and I tried....\n"
          . "Note: you probably need to read README.txt first.\n\n"
          . "I need some help here. You probably have OgreAL.pc (for pkg-config)\n"
          . "installed somewhere off the beaten path, like\n"
          . "$ENV{HOME}/.ogreal-install/lib/pkgconfig/ or wherever.\n\n"
          . "And that's okay....\n\n"
          . "But can can we put that in PKG_CONFIG_PATH? We can\n"
          . "if you give me the full path here.\n"
          . "If you prefer to set CFLAGS and LIBS explicitly,\n"
          . "just hit return. Where is OgreAL.pc ? ";
        my $val = ExtUtils::MakeMaker::prompt($msg, '');
        $val =~ s/(^\s+|\s+$)//g;   # no mo whitespace

        if ($val =~ m{^/}) {
            my $pcfile = File::Spec->catfile($val, 'OgreAL.pc');
            unless (-f $pcfile) {
                print "\nDidn't find '$pcfile'.\n";
                my $giving_up = ExtUtils::MakeMaker::prompt("Do you give up? ", 'Yeah');
                if ($giving_up =~ /^y/i) {
                    last REDO;
                }
            }

            $ENV{PKG_CONFIG_PATH} = '' unless exists $ENV{PKG_CONFIG_PATH};
            $ENV{PKG_CONFIG_PATH} = "$val:" . $ENV{PKG_CONFIG_PATH};
            my $msg = "\n'$val' added to PKG_CONFIG_PATH - Thanks!\n"
              . "One more to check for... openal.\n"
              . "It might be somewhere local, like\n"
              . "$ENV{HOME}/.openal-install/lib/pkgconfig/ or wherever,\n"
              . "probably called openal.pc. If you think it's already in PKG_CONFIG_PATH,\n"
              . "just hit return. Where is openal.pc ? ";
            my $val = ExtUtils::MakeMaker::prompt($msg, '');
            $val =~ s/(^\s+|\s+$)//g;   # no mo whitespace

            if ($val =~ m{^/}) {
                my $pcfile = File::Spec->catfile($val, 'openal.pc');
                unless (-f $pcfile) {
                    print "\nDidn't find '$pcfile'.\n";
                    my $giving_up = ExtUtils::MakeMaker::prompt("Do you give up? ", 'Yeah');
                    if ($giving_up =~ /^y/i) {
                        last REDO;
                    }
                }
            }
            elsif ($val =~ /\S/) {
                print "\nNo, I need a *full* path, absolute, starting with a SLASH.\n";
                redo REDO;
            }
            else {
                print "\nDone with PKG_CONFIG_PATH.\n";
            }
        }
        elsif ($val =~ /\S/) {
            print "\nNo, I need a *full* path, absolute, starting with a SLASH.\n";
            redo REDO;
        }
        else {
            print "\nOkay, let's forget about PKG_CONFIG_PATH, then.\n";
        }
    }

    unless (exists $ENV{PKG_CONFIG_PATH}) {
        print "\nSince you don't have PKG_CONFIG_PATH set,\n"
          . "I have some harder questions for you...\n";

        unless (exists $ENV{OGREAL_CFLAGS} && exists $ENV{OGREAL_LIBS}) {
            print "\nWhat CFLAGS (header locations, -I paths) should we use for OgreAL?\n";
            my $cflags = ExtUtils::MakeMaker::prompt("OGREAL_CFLAGS = ", '');
            if ($cflags =~ /\S/) {
                $ENV{OGREAL_CFLAGS} = $cflags;
            }

            print "\nWhat LIBS (library locations and libraries, -L and -l) should we use for OgreAL?\n";
            my $libs = ExtUtils::MakeMaker::prompt("OGREAL_LIBS = ", '');
            if ($libs =~ /\S/) {
                $ENV{OGREAL_LIBS} = $libs;
            }
        }

        unless (exists $ENV{OPENAL_CFLAGS} && exists $ENV{OPENAL_LIBS}) {
            print "\nWhat CFLAGS (header locations, -I paths) should we use for libopenal?\n";
            my $cflags = ExtUtils::MakeMaker::prompt("OPENAL_CFLAGS = ", '');
            if ($cflags =~ /\S/) {
                $ENV{OPENAL_CFLAGS} = $cflags;
            }

            print "\nWhat LIBS (library locations and libraries, -L and -l) should we use for libopenal?\n";
            my $libs = ExtUtils::MakeMaker::prompt("OPENAL_LIBS = ", '');
            if ($libs =~ /\S/) {
                $ENV{OPENAL_LIBS} = $libs;
            }
        }
    }

    unless (exists($ENV{PKG_CONFIG_PATH})
              or
            (exists($ENV{OGREAL_CFLAGS}) and exists($ENV{OGREAL_LIBS})
               and exists($ENV{OPENAL_CFLAGS}) and exists($ENV{OPENAL_LIBS}) ))
    {
        error("Giving up - don't know where OgreAL and libopenal are installed.");
    }
}

sub pkg_config_installed {
    my $pcver = `pkg-config --version`;
    return $pcver ne '';
}

sub check_pkg_config {
    my ($pkg, $required_version) = @_;

    my $pc = 'pkg-config';
    my @errors = ();

    # Check that pkg-config knows about the package
    my $pkgexists = `$pc --exists $pkg`;
    if ($?) {
        push @errors, "Package $pkg not found by $pc";
    }
    else {
        # Check that the package is the right version
        my $pkgver = `$pc --atleast-version='$required_version' $pkg`;
        if ($?) {
            push @errors, "Package $pkg is not the right version (at least $required_version)";
        }
    }

    return @errors;
}

sub pkg_config {
    my ($pkg, $option, $pc) = @_;

    $pc = 'pkg-config' unless defined $pc;

    my $str = `$pc --$option $pkg`;
    if ($?) {
        error("$pc --$option $pkg: $str");
    }
    else {
        chomp $str;
        return $str;
    }
}

sub error {
    my (@errors) = @_;
    push @errors, "Be sure to read README.txt!";
    die(map { "$_$/" } @errors);
}