# id3fs - a FUSE-based filesystem for browsing audio metadata
# Copyright (C) 2010  Ian Beckwith <ianb@erislabs.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

package ID3FS::AudioFile;

use strict;
use warnings;
use ID3FS::AudioFile::Mp3;
use ID3FS::AudioFile::Ogg;
use ID3FS::AudioFile::Flac;

sub new
{
    my $proto=shift;
    my $class=ref($proto) || $proto;
    my $self={};
    bless($self,$class);

    my $path=shift;
    my $ext=($path=~/.*\.(.*)/)[0];
    return undef unless($ext);
    my $me=shift;
    $ext=lc($ext);
    if($ext eq "mp3")
    {
	$self->{audiofile}=ID3FS::AudioFile::Mp3->new($path);
    }
    elsif($ext eq "ogg")
    {
	$self->{audiofile}=ID3FS::AudioFile::Ogg->new($path);
    }
    elsif($ext eq "flac")
    {
	$self->{audiofile}=ID3FS::AudioFile::Flac->new($path);
    }
    else
    {
	print("$me: $path: Unknown extension: $ext\n");
	return undef;
    }
    return $self;
}

sub set
{
    my ($self, $thing, $value)=@_;
    if($value)
    {
	$value=$self->sanitise($self->stripslashes($value));
	$self->{audiofile}->$thing($value);
    }
    else
    {
	$value=$self->sanitise($self->stripslashes($self->{audiofile}->$thing()));
    }
    return $value;
}

sub artist    { return(shift->set("artist", @_));   }
sub album     { return(shift->set("album", @_));    }
sub track     { return(shift->set("track", @_));    }
sub tracknum  { return(shift->set("tracknum", @_)); }
sub v1genre   { return(shift->set("v1genre", @_));  }
sub comment   { return(shift->set("comment", @_));  }
sub audiotype { return(shift->set("audiotype"));    }
sub haspic    { return(shift->set("haspic"));       }

sub delete_artist   { shift->{audiofile}->delete_artist();   }
sub delete_album    { shift->{audiofile}->delete_album();    }
sub delete_track    { shift->{audiofile}->delete_track();    }
sub delete_tracknum { shift->{audiofile}->delete_tracknum(); }
sub delete_year     { shift->{audiofile}->delete_year();     }
sub delete_v1genre  { shift->{audiofile}->delete_v1genre();  }
sub delete_comment  { shift->{audiofile}->delete_comment();  }
sub delete_all      { shift->{audiofile}->delete_all();      }
sub delete_genre    { shift->{audiofile}->delete_genre();    }
sub delete_tags     { shift->{audiofile}->delete_tags();     }

sub year
{
    my ($self, $year)=@_;
    if($year)
    {
	$year=$self->format_year($year);
	$self->{audiofile}->year($year);
    }
    else
    {
	$year=$self->{audiofile}->year();
    }
    return $year;
}

sub format_year
{
    my ($self, $year)=@_;
    if($year)
    {
	$year=$self->sanitise($self->stripslashes($year));
	if(defined($year) && $year =~/(\d{4})/)
	{
	    $year=$1;
	}
    }
    return $year;
}

sub add_tags
{
    my($self, $tags)=@_;
    die("FIXME: implement add_tags()\n");
}

sub tags
{
    my $self=shift;
    my @intags=$self->{audiofile}->tags();
    my @outtags=();
    return() unless(@intags);
    @intags = grep { defined($_); } @intags;
    # combine then split on commas
    # so multiple comma-delimited tags will work
    @intags=split(/\s*,\s*/, join(', ', @intags));
    for my $tag (@intags)
    {
	next unless(length($tag));
	next unless($tag =~ /\S+/);
	$tag=$self->sanitise($tag);
	my ($tagname, $tagval)=($tag, undef);
	if($tag=~/^([^\/]+)\/(.*)/)
	{
	    ($tagname, $tagval)=($1, $2);
	}
	push(@outtags, [ $tagname, $tagval ]);
    }
    return @outtags;
}

sub write
{
    shift->{audiofile}->write();
}

sub sanitise
{
    my ($self, $text)=@_;
    $text =~ s/[^[:print:]]//g if(defined($text));
    return $text;
}

sub stripslashes
{
    my ($self, $text)=@_;
    $text =~ s/\//-/g if(defined($text));
    return $text;
}

1;
