#!/usr/bin/perl -w
# ABSTRACT: a great way to tune an acoustic guitar

use 5.018;

use strict;

use Carp;

use Narwhal::Preset;

use constant (
  EPSILON => 0.000001,
  TIMEOUT => 14400.0,
);

use Narwhal::Synth;
use Narwhal::Tone::Pluck;
use Narwhal::Effect::Fade;

{ package Narwhal;
    
    use Carp;
    
    use Moose;
    use Moose::Util::TypeConstraints;
    
    use Getopt::Long;
    
    use YAML::Tiny;
    
    use Data::Dumper;
    
    use constant DEFAULT_FORMAT => 'YAML';
    
    # local $YAML::SortKeys = 0;
    
    enum 'Format', [qw(YAML XML JSON)];
    
    has 'format' => (
        is => 'rw',
        isa => 'Format',
    );
    
    has 'preset' => (
        is => 'rw',
        isa => 'Narwhal::Preset',
    );
    
    sub proc_options {
        my $self = shift;    
        my $opt_format = DEFAULT_FORMAT;
        eval {
            GetOptions('format=s' => \$opt_format);
            $self->format($opt_format);
        };
      
        die "Regrettably, this is not a valid format option.  Choose one of (YAML,JSON or XML)." if $@;
      
        return(0);
    }
    
    sub begin {
        my $self = shift;
        $self->proc_options();
        return(0);
    }
    
    sub capture {
        my @lines = <>;
        my $diamond = "@lines";
        
        if($diamond) {
            return($diamond);
        } else {
            return(0);
        }
    }
    
    sub parse {
        my $self = shift;
        $self->preset(Narwhal::Preset->new(format => $self->format,diamond => $self->capture));
        if($self->preset->parse()) {
            say "Preset parsed with success.";
        }
    }
    
    sub proc_preset {
        my $self = shift;
        
        my $cfg_preset = $self->preset->buffer->{preset} or die("Syntax error: preset element not found");
        my $cfg_synth = $cfg_preset->{synth} or die("Syntax error: synth element not found");
        my $cfg_tone = $cfg_synth->{tone} or die("Syntax error: tone element not found");
        my $cfg_effect = $cfg_preset->{effect} or die("Syntax error: effect element not found");
        
        $self->preset->process($cfg_preset->{process});
        
        $self->preset->synth(Narwhal::Synth->new(%$cfg_synth)) if $cfg_synth;
        
        $self->preset->tone(Narwhal::Tone::Pluck->new(%{$cfg_tone->{pluck}})) if $cfg_tone and exists($cfg_tone->{pluck});
        
        $self->preset->effect(Narwhal::Effect::Fade->new(%{$cfg_effect->{fade}})) if $cfg_effect and exists($cfg_effect->{fade});
    }
    
    sub soxi {
        my $self = shift;
        my $handle = "-n"; # null file handle
        my $ret = sprintf("%s %s %s %s",$self->preset->process,$handle,$self->preset->tone->soxi($self->preset->synth),$self->preset->effect->soxi());
        return($ret);
    }
}

1;
