#!/usr/bin/perl -w

use strict;
use open qw(:std :encoding(utf8));
use Net::MQTT::Simple;
use Getopt::Long qw(GetOptions);

my $usage = "Usage: man mqtt-simple ;-)\n";

my @colors = qw(33;1 32;1 31;1 35;1 36;1 37;1 33 32 31 35 36); 

GetOptions(
    "h|host=s"          => \my $host,
    "c|color"           => \my $color,
    "s|t|subscribe=s"   => \my @topics,
    "p|publish=s"       => \my $publish,
    "r|retain"          => \my $retain,
    "m|message=s"       => \my $message,
) or die $usage;

$host or die $usage;

my $m = Net::MQTT::Simple->new($host);

defined $publish or @topics or die $usage;

if (defined $publish) {
    my $method = $retain ? "retain" : "publish";
    if (defined $message) {
        $m->$method($publish, $message);
    } else {
        while (defined (my $line = readline *STDIN)) {
            chomp $line;
            $m->$method($publish, $line);
        }
    }
} elsif (defined $message) {
    die "-m requires -p. $usage";
} elsif ($retain) {
    die "-r requires -p. $usage";
}

if (@topics) {
    my $i = 0;
    for (@topics) {
        my $ansi = $color
            ? "\e[$colors[ $i % @colors ]m"
            : "";
        my $ansi_reset = $color ? "\e[0m" : "";
        $i++;

        $m->subscribe(
            $_ => sub {
                my ($topic, $message) = @_;
                print "$ansi$topic$ansi_reset $message\n";
            });
    }
    $m->run;
} elsif ($color) {
    die "-c requires -s. $usage";
}

__END__

=head1 NAME

mqtt-simple - Very simple MQTT implementation

=head1 SYNOPSIS

 mqtt-simple -h mqtt.example.org -c -s "sensors/#" -s "debug/#" -s "#"

 mqtt-simple -h mqtt.example.org -p "example/unretained" -m "message"

 mqtt-simple -h mqtt.example.org -r -p "example/retained" -m "message"

 tail -f logfile | mqtt-simple -h mqtt.example.org -p "log/example"

=head1 DESCRIPTION

This is just a simple utility program. It doesn't do much. Specifically, all
the QoS and security features are unsupported. Also, don't expect fancy error
messages and such :-)

=head1 COMMAND LINE OPTIONS

=over 25

=item -h --host

MQTT server to connect to, required.

=item -p --publish I<topic>

Publish a message. Uses the message given with C<-m>, or will read lines from
B<stdin>, and publish a message for each given line.

=item -m --message I<message>

Message to publish. Requires C<-p>.

=item -r --retain

Causes messages published with C<-p> to have the "retain" flag on.

=item -s --subscribe I<filter>

Subscribe to the given topic filter. Use the standard MQTT wildcards like
C<+> and C<#>. Outputs matching published messages on B<stdout>.

=item -c --color

For each given C<-s>, print the matching topic in a different color. Note that
the first matching topic will be used for color selection, so specify the topics
with the most specific one first, the least specific one (like C<#>) last.

=back

=head1 LICENSE

Pick your favourite OSI approved license :)

http://www.opensource.org/licenses/alphabetical

=head1 AUTHOR

Juerd Waalboer <juerd@tnx.nl>

=head1 SEE ALSO

L<Net::MQTT::Simple>

