package App::EventStreamr;
use v5.010;
use strict;
use warnings;
use Method::Signatures;
use experimental 'switch';
use Module::Load;
use App::EventStreamr::Internal::API;
use Moo;
use namespace::clean;

# ABSTRACT: Conference Mixing/Streaming Orchestrator

our $VERSION = '0.5'; # VERSION: Generated by DZP::OurPkg:Version


use App::EventStreamr::Config;

has 'debug' => ( is => 'ro', default => sub { 0 } );
has '_log_level' => ( is => 'ro', lazy => 1, builder => 1 );

method _build__log_level() {
  if ($self->debug) {
    return "DEBUG, LOG1, SCREEN";
  } else {
    return "INFO, LOG1";
  }
}

has 'config' => (
  is => 'rw',
  isa => sub { "App::EventStreamr::Config" },
  lazy => 1,
  builder => 1,
  handles => [ qw( configure write_config ) ],
);

method _build_config() {
  return App::EventStreamr::Config->new(
    log_level => $self->_log_level,
  );
}

use App::EventStreamr::Status;

has 'status' => (
  is => 'rw',
  isa => sub { "App::EventStreamr::Status" },
  lazy => 1,
  builder => 1,
  handles => [ qw( starting stopping restarting set_state threshold post_status ) ],
);

method _build_status() {
  return App::EventStreamr::Status->new(
    config => $self->config,
  );
}

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

method _load_package($type,$package) {
  my $pkg = "App::EventStreamr::".$type."::".$package;
  load $pkg;
  $self->_processes->{$package} = $pkg->new(
    config => $self->config,
    status => $self->status,
  );
}

method start() {
  # Load API
  $self->info("Manager starting: pid=$$, station_id=".$self->config->macaddress);

  # Internal Processes
  $self->_load_package("Internal","API");
  $self->_processes->{API}->run_stop();
  $self->_load_package("Internal","Devmon");
  $self->_processes->{Devmon}->run_stop();
  $self->config->post_config();
  
  # Roles
  foreach my $role (@{$self->config->roles}) {
    $self->_load_package($self->config->backend,ucfirst($role));
  }
}

method run() {
  $self->start();
  while (1 == 1) {
    foreach my $key (keys %{$self->_processes}) {
      $self->_processes->{$key}->run_stop();
    }
    sleep 1;

    # Once a loop is completed the devices will have been
    # stopped.
    # TODO: Do this better.
    if ($self->config->run == 2) {
      foreach my $key (keys %{$self->_processes}) {
        if ( $self->_processes->{$key}->type() ne "internal" ) {
          $self->info("Stopping: ".$self->_processes->{$key}->id());
          $self->_processes->{$key}->stop();
        }
      }
      $self->config->run('1');
      $self->config->dvswitch_running('0');
    }
  }
}

method stop() {
  $self->info("Manager stopping: pid=$$, station_id=".$self->config->macaddress);
  foreach my $key (keys %{$self->_processes}) {
    if ( $self->_processes->{$key}->type() eq "internal" ) {
      $self->info("Stopping: ".$self->_processes->{$key}->id());
      $self->_processes->{$key}->stop();
    }
  }
  $self->info("Manager stopped: pid=$$, station_id=".$self->config->macaddress);
  exit 0;
}

with('App::EventStreamr::Roles::Logger');


1;

__END__

=pod

=encoding UTF-8

=head1 NAME

App::EventStreamr - Conference Mixing/Streaming Orchestrator

=head1 VERSION

version 0.5

=head1 SYNOPSIS

  use App::EventStreamr;

  my $eventstreamr = App::EventStreamr->new();

=head1 DESCRIPTION

Born due to the instability of DVswitch, EventStreamr attempts to 
remove the time consuming process that is connecting up all the 
devices and ensuring they stay connected.

First you should configure the system, although if using in 
conjunction with the frontend it will provide a number of useful
defaults.

  eventstreamr --configure

Once configured you can add 'eventstreamr' as a startup process
or launch from the cli.

  eventstreamr

=head1 ACKNOWLEDGEMENTS

Jason Nicholls for finding all the bugs and writing the status display.

Luke John for all the help with the frontend code. 

=head1 BUGS/Feature Requests

Please submit any bugs, feature requests to
L<https://github.com/plugorgau/eventstreamr-station/issues> .

Contributions are more than welcome! I am aware that Dist::Zilla 
comes with quite a dependency chain, so feel free to submit pull 
request with code + explanation of what you are trying to achieve 
and I will test and likely implement them.

=head1 Known Issues

Daemon dies when alsa device isn't present on start - L<https://github.com/plugorgau/eventstreamr-station/issues/54>
Workaround: Ensure all configured ALSA devices are plugged in on boot

Correctly Restart on Date Change - L<https://github.com/plugorgau/eventstreamr-station/issues/18>
Workaround: Reboot or Restart the EventStreamr Daemon (pressing update from the controller will restart it)

=head1 AUTHOR

Leon Wright < techman@cpan.org >

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2014 by Leon Wright.

This is free software, licensed under:

  The GNU Affero General Public License, Version 3, November 2007

=cut