#!/usr/bin/perl -w -I ../../lib

use 5.018;

use strict;

use Carp;

{ package Audio::Signal::Preset;
  
    use Moose;
    use Moose::Util::TypeConstraints;
    
    use YAML::Tiny;

    use Data::Dumper;       
    
    enum 'Format', [qw(YAML XML JSON)];
    enum 'Process', [qw(sox play)];
    enum 'TTY', [qw(STDOUT STDERR)];
    enum 'Handle', ['-n'];
    
    our %gencmd_handle = (
        'null' => '-n',
    );
    
    has 'format' => (
        is => 'rw',
        isa => 'Format',
    );

    has 'diamond' => (
        is => 'rw',
        isa => 'Str',
    );

    has 'buffer' => (
        is => 'rw',
        isa => 'HashRef',
    );
      
    has 'process' => (
        is => 'rw',
        isa => 'Process',
    );
    
    has 'tty' => (
        is => 'rw',
        isa => 'TTY',
    );
    
    has 'say' => (
        is => 'rw',
        isa => 'Str',
    );
    
    has 'handle' => (
        is => 'rw',
        isa => 'Handle',
    );
  
    has 'synths' => (
        is => 'rw',
        isa => 'ArrayRef',
        default => sub { return([]); },
    );
    
    sub parse {
        my $self = shift;
        my $yaml;
        given($self->format) {
            when(/^YAML$/) {                
                eval {
                    $yaml = YAML::Tiny->read_string($self->diamond);
                };
                die "Regrettably, this file is not a valid audio::signal preset. $@." if $@;
                $self->buffer($yaml->[0]) or die "Regrettably, this file is not a valid audio::signal preset.";
                return(1);
            }
        }
        
        return(0);
    }
    
    sub proc_preset_attributes {
        my $self = shift;
        my $cfg_preset = shift;
        
        # preset attributes
        $self->tty($cfg_preset->{tty});
        $self->say($cfg_preset->{say});
        $self->process($cfg_preset->{process});
        $self->handle($Audio::Signal::Preset::gencmd_handle{$cfg_preset->{handle}});
        
        return(1);
    }
    
    sub proc_synth_collection {
        my $self = shift;
        my $cfg_synths = shift;
        
        for my $cfg_synth (@{$cfg_synths}) {
            while(my ($cfg_synth_type,$cfg_synth_attrs) = each($cfg_synth)) {                
                push(@{$self->synths}, Audio::Signal::Synth->new($cfg_synth_attrs));
            }
        }
        
        return(1);
    }
    
    sub proc {
        my $self = shift;
        
        # preset attributes
        my $cfg_preset = $self->buffer->{preset} or die("Syntax error: preset attributes not found");        
        $self->proc_preset_attributes($cfg_preset);
        
        # synth collection
        my $cfg_synths = $cfg_preset->{synths} or die("Syntax error: synth collection not found");        
        $self->proc_synth_collection($cfg_synths);
        
        return(1);
    }
}

1;
