#!/usr/bin/perl

#  You may distribute under the terms of the GNU General Public License
#
#  (C) Paul Evans, 2010-2021 -- leonerd@leonerd.org.uk

use strict;
use warnings;

use Tickit::Async;
use Tickit::Widget::Tabbed 0.005;
use Tickit::Widget::VBox;
use Tickit::Window 0.57;  # ->bind_event

use Tickit::App::Plugin::EscapePrefix;

use Net::Async::Tangence::Client 0.15; # ->connect_url 'family' argument

use Circle::FE::Term::Tab;
use Circle::FE::Term::Ribbon;

use IO::Async::Loop;

use Text::Balanced qw( extract_bracketed );
use Getopt::Long;

my $loop = IO::Async::Loop->new();

use constant HAVE_METRICS => eval { require Metrics::Any::Adapter; };

my $IDENTITY;
my $FAMILY;

GetOptions(
   'identity|i=s' => \$IDENTITY,
   'metrics-port=i' => \my $METRICS_PORT,
   'help' => sub { usage(0) },
   '4|ipv4' => sub { $FAMILY = "inet4" },
   '6|ipv6' => sub { $FAMILY = "inet6" },
) or usage(1);

sub usage
{
   my ( $exitcode ) = @_;

   print { $exitcode ? \*STDERR : \*STDOUT } <<'EOF';
circle-fe-term [options...] [URL]

Options:

   --identity, -i IDENTITY   Use the given session identity for reconnection

URL should be one of:

   sshunix://host/path/to/socket
   sshexec://host/path/to/command?with+arguments
   exec:///path/to/command?with+arguments
   tcp://host:port/
   unix:///path/to/socket

EOF

   exit $exitcode;
}

if( HAVE_METRICS and $METRICS_PORT ) {
   Metrics::Any::Adapter->import( 'Prometheus' );

   require Net::Prometheus;
   Net::Prometheus->new->export_to_IO_Async( $loop, port => $METRICS_PORT );
};

my $URL = shift @ARGV or usage(1);

if( !defined $IDENTITY ) {
   my $hostname = `hostname -f`; chomp $hostname;
   $IDENTITY = $ENV{USER} . "@" . $hostname . "/Term";
}

my $client = Net::Async::Tangence::Client->new(
   identity => $IDENTITY,

   on_closed => sub {
      warn "Connection closed\n";
      exit(0);
   },

   on_error => sub { warn "Received MSG_ERROR: $_[0]\n"; },
);

$loop->add( $client );

my $rootobj = $client->connect_url( $URL, family => $FAMILY )->get;

my $t = Tickit::Async->new;

$loop->add( $t );

Tickit::App::Plugin::EscapePrefix->apply( $t );

my $top_vbox = Tickit::Widget::VBox->new;

# TODO: Consider a menubar

my $tabbed = Tickit::Widget::Tabbed->new(
   tab_position => "bottom",
   pen_active   => Tickit::Pen->new( b => 1, u => 1 ),
   tab_class    => "Circle::FE::Term::Tab",
   ribbon_class => "Circle::FE::Term::Ribbon",
);

$t->bind_key( "C-n" => sub { $tabbed->next_tab } );
$t->bind_key( "C-p" => sub { $tabbed->prev_tab } );

$top_vbox->add( $tabbed, expand => 1 );

$t->set_root_widget( $top_vbox );

my $f = $rootobj->call_method(
   "get_session" => [ 'tabs' ],
)->then( sub {
   my ( $session ) = @_;

   $session->watch_property_with_initial( "tabs",
      on_set => sub {
         my ( $objarray ) = @_;

         foreach my $obj ( @$objarray ) {
            $tabbed->add_tab( Tickit::Widget::VBox->new, object => $obj );
         }
      },
      on_push => sub {
         my @new = @_;
         foreach my $obj ( @new ) {
            $tabbed->add_tab( Tickit::Widget::VBox->new, object => $obj );
         }
      },
      on_shift => sub {
         my ( $count ) = @_;
         $tabbed->remove_tab( 0 ) for 1 .. $count;
      },
      on_splice => sub {
         my ( $index, $count, @objs ) = @_;

         # $count times, remove the one at $index, as they'll shuffle down
         $tabbed->remove_tab( $index ) for 1 .. $count;

         # TODO: I have no idea wtf is going on here
         foreach my $i ( 0 .. $#objs ) {
            my $obj = $objs[$i];
            die "TODO: insert tab\n";
         }
      },
      on_move => sub {
         my ( $index, $delta ) = @_;

         $tabbed->move_tab( $index, $delta );
      },
   );
});
$t->adopt_future( $f );

$t->run;
