package App::Clifton::Server;

use aliased 'App::Clifton::ConsoleService';
use aliased 'App::Clifton::ConfigLoader';
use aliased 'App::Clifton::Tower::Jabber' => 'Jabber_Tower';
use aliased 'App::Clifton::Tower::IRC' => 'IRC_Tower';
use Moo;

extends 'App::Clifton::Service';

sub BUILD {
  my ($self, $args) = @_;
  $args->{loop}->add($self);
  $self->$_ for qw(console_service);
}

has config_file => (is => 'ro', required => 1);

has config_loader => (is => 'lazy');

has current_config => (is => 'rw');

sub _build_config_loader { ConfigLoader->new }

has console_service => (is => 'lazy');

has jabber_towers => (is => 'ro', default => sub { {} });

has irc_towers => (is => 'ro', default => sub { {} });

sub _build_console_service {
  my ($self) = @_;
  $self->_new_child(ConsoleService, { server => $self });
}

sub reload_config { shift->_do(reload_config => @_) }
sub shutdown { shift->_do(shutdown => @_) }

sub _body_for_reload_config {
  my ($self, $args) = @_;
  my $config = $self->config_loader->config_from_file($self->config_file);
  my $jt = $self->jabber_towers;
  foreach my $bridge ($config->bridges->flatten) {

    $jt->{$bridge->name} = $self->_new_child(
      Jabber_Tower, {
        jabber_config => $bridge->jabber,
        irc_config => $bridge->irc,
        bridge_name => $bridge->name,
        server => $self,
      }
    );
  }
  foreach my $user ($config->users->flatten) {
    $jt->{$_}->userconfig_set->add($user) for @{$user->allow};
  }
  $self->current_config($config);
  $args->{on_finished}->($config);
}

sub start_chain { shift->_do(start_chain => @_) }

sub _dependencies_for_start_chain {
  my ($self, $args) = @_;
  {
    irc_tower => $self->start_irc_tower($args->{irc_tower})
  }
}

sub _body_for_start_chain {
  my ($self, $args) = @_;
  $args->{irc_tower}->start_chain($args);
}

sub start_irc_tower { shift->_do(start_irc_tower => @_) }

sub _guard_for_start_irc_tower {
  my ($self, $args) = @_;
  if (my $tower = $self->irc_towers->{$args->{server}}{$args->{irc_nick}}) {
    ($tower);
  } else {
    ();
  }
}

sub _body_for_start_irc_tower {
  my ($self, $args) = @_;
  $self->_new_child(IRC_Tower, {
    irc_server => $args->{server},
    irc_nick => $args->{irc_nick},
    on_setup => $args->{on_finished},
    server => $self,
  });
}

1;
