#!/usr/bin/perl

# Created on: 2012-05-27 18:58:06
# Create by:  Ivan Wills
# $Id$
# $Revision$, $HeadURL$, $Date$
# $Revision$, $Source$, $Date$

use strict;
use warnings;
use version;
use Scalar::Util;
use List::Util;
#use List::MoreUtils;
use Getopt::Long;
use Pod::Usage;
use Data::Dumper qw/Dumper/;
use English qw/ -no_match_vars /;
use FindBin qw/$Bin/;
use Path::Class;
use W3C::SOAP::WSDL::Parser;
use File::ShareDir qw/dist_dir/;
use Template;

our $VERSION = version->new('0.0.3');
my ($name)   = $PROGRAM_NAME =~ m{^.*/(.*?)$}mxs;

my %option = (
    lib           => 'lib',
    ns_module_map => {},
    verbose       => 0,
    man           => 0,
    help          => 0,
    VERSION       => 0,
);

if ( !@ARGV ) {
    pod2usage( -verbose => 1 );
}

main();
exit 0;

sub main {

    Getopt::Long::Configure('bundling');
    GetOptions(
        \%option,
        'ns_module_map|ns|namespace-map|n=s%',
        'ns_module_map_file|map-file|f=s',
        'lib|l=s',
        'show|s',
        'path|p=s',
        'save|S',
        'verbose|v+',
        'man',
        'help',
        'VERSION!',
    ) or pod2usage(2);

    if ( $option{'VERSION'} ) {
        print "$name Version = $VERSION\n";
        exit 1;
    }
    elsif ( $option{'man'} ) {
        pod2usage( -verbose => 2 );
    }
    elsif ( $option{'help'} ) {
        pod2usage( -verbose => 1 );
    }

    if ( $option{ns_module_map_file} && -f $option{ns_module_map_file} ) {
        $option{ns_module_map} ||= {};
        my $file = file $option{ns_module_map_file};

        for my $line ($file->slurp) {
            chomp $line;
            my ($ns, $mod) = split /,|\t/, $line, 2;
            $option{ns_module_map}{$ns} ||= $mod
        }
    }
    #warn Dumper $option{ns_module_map}, $option{ns_module_map_file};

    return show() if $option{show};

    my $template = Template->new(
        INCLUDE_PATH => ($option{path} ? "$option{path}:" : '') . dist_dir('W3C-SOAP'),
        INTERPOLATE  => 0,
        EVAL_PERL    => 1,
    );

    die Dumper \@ARGV if @ARGV % 2;
    my %map = @ARGV;
    for my $module (keys %map) {
        my $wsdl = W3C::SOAP::WSDL::Parser->new(
            location => $map{$module},
            template => $template,
            module   => $module,
            %option,
        );
        $wsdl->write_modules;

        if ( $option{save} ) {
            my $file = $map{$module};
            $file =~ s{[/:?&]}{_}g;
            my $fh = file("$file.wsdl")->openw;
            print {$fh} $wsdl->document->xml->toString();

            for my $schema ($wsdl->get_xsd->get_schemas) {
                next if ! $schema->location;
                my $file = $schema->location;
                $file =~ s{[/:?&]}{_}g;
                my $fh = file("$file.xsd")->openw;
                print {$fh} $schema->xml->toString();
            }
        }
    }

    return;
}

sub show {
    # do stuff here
    my %map = @ARGV;
    for my $module (keys %map) {
        my $wsdl = W3C::SOAP::WSDL::Document->new(
            %option,
            location => $map{$module},
        );
        print $wsdl->target_namespace, "\n";
        print "Messages :\n";
        for my $node (@{ $wsdl->messages }) {
            print "\t", $node->name, "\n";
        }
        print "Port Types :\n";
        for my $node (@{ $wsdl->port_types }) {
            print "\t", $node->name, "\n";
        }
        print "Bindings :\n";
        for my $node (@{ $wsdl->bindings }) {
            print "\t", $node->name, "\n";
        }
        print "Servicess :\n";
        for my $node (@{ $wsdl->services }) {
            print "\t", $node->name, "\n";
            for my $port (@{ $node->ports }) {
                print "\t\t", $port->binding->name, ' : ', $port->address, "\n";
                for my $operation (@{ $port->binding->operations }) {
                    print "\t\t\t", $operation->name, "\n";
                    for my $dir (qw/inputs outputs/) {
                        print "\t\t\t\t$dir: ";
                        if ($operation->port_type->$dir->[0]->message->element) {
                            print $operation->port_type->$dir->[0]->message->element->type_module;
                        }
                        elsif ($operation->port_type->$dir->[0]->message->type) {
                            print $operation->port_type->$dir->[0]->message->type;
                        }
                        print "\n";
                    }
                }
            }
        }
    }

    return;
}

__DATA__

=head1 NAME

wsdl-parser - Parses a WSDL file to generate a SOAP client

=head1 VERSION

This documentation refers to wsdl-parser version 0.0.3.

=head1 SYNOPSIS

   wsdl-parser [option] package wsdl_file_or_url

 OPTIONS:
  -s --show     Show some info about the passed WSDL file
  -n --namespace-map ns=package
                A mapping of XSD namespaces (ns) to perl package names, it
                is required when writing XSD files
  -f --map-file[=]file
                File that contains mappings of name
  -l --lib[=]dir
                Directory where generated modules should be writted, the
                default is ./lib
  -p --path[=]str
                Extra template toolkit directories if you want to override
                default templates.
  -S --save     Save all downloaded WSDLs & XSDs

  -v --verbose  Show more detailed option
     --version  Prints the version information
     --help     Prints this help information
     --man      Prints the full documentation for wsdl-parser

=head1 DESCRIPTION



=head1 SUBROUTINES/METHODS

=over 4

=back

=head1 CONFIGURATION AND ENVIRONMENT

=head1 DEPENDENCIES

=head1 INCOMPATIBILITIES

=head1 BUGS AND LIMITATIONS

There are no known bugs in this module.

Please report problems to Ivan Wills (ivan.wills@gmail.com).

Patches are welcome.

=head1 AUTHOR

Ivan Wills - (ivan.wills@gmail.com)

=head1 LICENSE AND COPYRIGHT

Copyright (c) 2012 Ivan Wills (14 Mullion Close, Hornsby Heights, NSW Australia 2077).
All rights reserved.

This module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself. See L<perlartistic>.  This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

=cut
