use strict;
use warnings;

#--------------------------------------------------------------------------------------------------------------
# fixname
#--------------------------------------------------------------------------------------------------------------

sub fixname {
        if(!$_) { return; }     # prevent null entrys being processed

        $main::id3_writeme = 0;

        # -----------------------------------------
	# local Vars
        # -----------------------------------------
	my $file 	= $_;
        my $newfile	= $file;
        my $tmpr 	= 1;
        my @tmp_arr;

        my $tag 	= 0;
        my $art 	= "";
        my $tit		= "";
        my $tra		= "";
        my $alb		= "";
        my $gen		= "";
        my $year	= "";
        my $com		= "";
        my $newart 	= "";
        my $newtit	= "";
        my $newtra	= "";
        my $newalb	= "";
        my $newgen	= "";
        my $newyear	= "";
        my $newcom	= "";

        my $tmp	       		= "";
        my $t_s	       		= "";
        my $tl	       		= 0;
        my $file_ext_length	= 0;
        my $trunc_char_length	= 0;
        my $l	       		= 0;
        my $enum_n		= 0;
        my $file_ext		= "";
        my $tmpfile		= "";

        $main::cwd = cwd;

        # -----------------------------------------
	# make sure file is allowed to be renamed
        # -----------------------------------------

        if((!-d $file) && ($main::ig_type || $file =~ /\.($main::file_ext_2_proc)$/i)) {
                $tmpr = 0;
        }

        if($main::proc_dirs && -d $file) {
                $tmpr = 0;
        }

        if($main::proc_dirs && $main::ig_type) {
                $tmpr = 0;
        }

        if(&match_filter($file) == 0) {
        	return;
        }

        if($tmpr == 1) {
        	return;
        }

	# Print dir if pwd != last dir (for recursive mode).

	if(
        	$main::recr &&
                $main::last_recr_dir ne "$main::cwd" &&
                $main::proc_dirs == 0
        ) {
		$main::last_recr_dir = $main::cwd;

		&nf_print(" ");
		&nf_print($main::cwd);
	}

	# Fetch mp3 tags if file is a mp3 and id3 mode is enabled
	# $tag will =1 only if tags r found & id3 mode is enabled

	if($main::id3_mode & $file =~ /.*\.mp3$/) {
		@tmp_arr = &get_tags($file);
		if($tmp_arr[0] eq "id3v1") {
			$tag = 1;
			$newart 	= $art 		= $tmp_arr[1];
			$newtit 	= $tit 		= $tmp_arr[2];
			$newtra 	= $tra 		= $tmp_arr[3];
			$newalb 	= $alb 		= $tmp_arr[4];
                        $newgen		= $gen	 	= $tmp_arr[5];
                        $newyear 	= $year		= $tmp_arr[6];
			$newcom 	= $com 		= $tmp_arr[7];
		}
	}

	# ---------------------------------------
	# Stuff todo before 1st basic cleanup
	# ---------------------------------------

	# Scenify Season & Episode numbers

	if($main::scene) 
	{
		$newfile =~ s/(^|\W)(\d+)(x)(\d+)/$1.qw(S).$2.qw(E).$4/ie;
	}

	# Unscene Season & Episode numbers

	if($main::unscene) 
	{
		$newfile =~ s/(S)(\d+)(E)(\d+)/$2.qw(x).$4/ie;
	}

	# remove patterns

        if($main::kill_sp_patterns) 
        {
                for (@main::kill_patterns_arr) 
                {
                        $newfile =~ s/$_//ig;
                }
        }

        # remove list of words

        if($main::kill_cwords)
        {
        	if(-d $file)
                {

	                for(@main::kill_words_arr)
                        {
	                        $newfile =~ s/(^|-|_|\.|\s+|\,|\+|\(|\[)($_)(\]|\)|-|_|\.|\s+|\,|\+|$)/$1.$3/eig;
	                }
		}
                else
                {
	                for(@main::kill_words_arr)
                        {
	                        $newfile =~ s/(^|-|_|\.|\s+|\,|\+|\(|\[)($_)(\]|\)|-|_|\.|\s+|\,|\+)/$1.$3/eig;
	                }
                }
        }

	# remove user entered word (also replace if anything is specified)

        if($main::replace) 
        {
                $newfile =~ s/($main::rpwold_escaped)/$main::rpwnew/ig;
        }

	# Front append

        if($main::front_a) 
        {
                $newfile = $main::faw.$newfile;
        }

	# End append

        if($main::end_a) 
        {
                $newfile =~ s/(.*)(\..*$)/$1$main::eaw$2/g;
        }

	# convert underscores to spaces

        if($main::spaces) 
        {
                # underscores to spaces
                $newfile =~ s/(\s|_)+/$main::space_character/g;

                if($tag) 
                {
                	$newart =~ s/(\s|_)+/$main::space_character/g;
			$newtit =~ s/(\s|_)+/$main::space_character/g;
			$newalb =~ s/(\s|_)+/$main::space_character/g;
			$newcom =~ s/(\s|_)+/$main::space_character/g;
                }
        }

	# pad -

	if($main::pad_dash == 1) 
	{
		$newfile =~ s/(\s*|_|\.)(-)(\s*|_|\.)/$main::space_character."-".$main::space_character/eg;
	}

	# Dots to spaces

        if($main::dot2space) 
        {
        	if(-d $file) 
        	{
        		$newfile =~ s/\./$main::space_character/g;
        	}
        	else 
        	{
                	$newfile =~ s/\./$main::space_character/g;
	                # put last dot back in front of the ext
        	        # there may be a cleaner way to do this but oh well
                	$newfile =~ s/(.*)($main::space_character)(.{3,4}$)/$1\.$3/g;
                }
        }

	# remove nasty characters

        if($main::sp_char) 
        {
                $newfile =~ s/[\~\@\%\{\}\[\]\"\<\>\!\`\'\,\#\(|\)]//g;
        }

	# remove all digits

        if($main::rm_digits) 
        {
        	$t_s = "";
                $newfile =~ s/\d+//g;
        }

	# remove digits from front of filename

        if($main::digits) 
        {
                # remove leading digits (Track Nr)
                $newfile =~ s/^\d*\s*//;
        }

        if($main::split_dddd) {
        	if($newfile =~ /(.*?)(\d{3,4})(.*)/)
                {
	                @tmp_arr = ($1, $2, $3);
	                if(length $tmp_arr[1] == 3)
                        {
	                        $tmp_arr[1] =~ s/(\d{1})(\d{2})/$1."x".$2/e;
	                        $newfile = $tmp_arr[0].$tmp_arr[1].$tmp_arr[2];
	                }
	                elsif(length $tmp_arr[1] == 4)
                        {
                        	if($tmp_arr[1] !~ /^(19|20)(\d+)/)
                                {
	                                $tmp_arr[1] =~ s/(\d{2})(\d{2})/$1."x".$2/e;
	                                $newfile = $tmp_arr[0].$tmp_arr[1].$tmp_arr[2];
                                }
	                }

                }
        }

	# ----------------------------------
        # Preliminary cleanup
	# ----------------------------------

        if($main::cleanup == 1) 
        {
                # "fix Artist - - track" type filenames that can pop up when stripping words
                $newfile =~ s/-(\s|_|\.)+-/-/g;

                # rm trailing characters
                $newfile =~ s/(\s|_|\.|-)+(\..{3,4})$/$2/e;

                # remove leading chars
                $newfile =~ s/^(\s|_|\.|-)+//;

                # I hate mpeg or jpeg as extensions personally :P
                $newfile =~ s/\.mpeg$/\.mpg/i;
                $newfile =~ s/\.jpeg$/\.jpg/i;
        }


	# International Character translation
        # WARNING: This might break really badly on some systems, esp. non-Unix ones...
	# if you see alot of ? in your filenames, you need to add the correct codepage for the filesystem.
	
        if($main::intr_char) 
        {
                $newfile =~ s/Å/Aa/g;
                $newfile =~ s/Ä/Ae/g;
                $newfile =~ s/Á/A/g;
                $newfile =~ s/Æ/ae/g;

		$newfile =~ s/ß/ss/g;

                $newfile =~ s/É/E/g;

                $newfile =~ s/Í/I/g;

		$newfile =~ s/Ñ/N/g;

		$newfile =~ s/Ó/O/g;
                $newfile =~ s/Ö/Oe/g;
                $newfile =~ s/Ø/Oo/g;

                $newfile =~ s/Ü/Ue/g;
		$newfile =~ s/Ú/U/g;

                $newfile =~ s/ã/a/g;
                $newfile =~ s/à/a/g;	# mems 1st addition to int support
                $newfile =~ s/á/a/g;
                $newfile =~ s/å/aa/g;
                $newfile =~ s/æ/ae/g;
                $newfile =~ s/ä/ae/g;

		$newfile =~ s/ç/c/g;

                $newfile =~ s/é/e/g;
		$newfile =~ s/è/e/g;

                $newfile =~ s/í/i/g;

		$newfile =~ s/ñ/n/g;

                $newfile =~ s/ø/oo/g;
                $newfile =~ s/ö/oe/g;
		$newfile =~ s/ó/o/g;
		$newfile =~ s/ô/o/g;

		$newfile =~ s/ú/u/g;
                $newfile =~ s/ü/ue/g;

		$newfile =~ s/¿//g;
		$newfile =~ s/¡//g;
		$newfile =~ s/´//g;
        }

	# Apply casing

        if($main::case) 
        {
                $newfile =~ s/(^| |\.|_|\(|-)([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü])(([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü]|\'|\¿|\¡|\´)*)/$1.uc($2).lc($3)/eg;
                if($tag) 
                {
                	$newart =~ s/(^| |\.|_|\(|-)([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü])(([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü]|\'|\¿|\¡|\´)*)/$1.uc($2).lc($3)/eg;
                	$newtit =~ s/(^| |\.|_|\(|-)([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü])(([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü]|\'|\¿|\¡|\´)*)/$1.uc($2).lc($3)/eg;
                	$newalb =~ s/(^| |\.|_|\(|-)([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü])(([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü]|\'|\¿|\¡|\´)*)/$1.uc($2).lc($3)/eg;
                	$newcom =~ s/(^| |\.|_|\(|-)([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü])(([A-Za-zÅÄÁÆßÉÍÑÓÖØÜÚãàáåæäçéèíñøöóôúü]|\'|\¿|\¡|\´)*)/$1.uc($2).lc($3)/eg;
                }
        }

        # Specific word casing

        if($main::sp_word) 
        {
        	my $word = "";
                foreach $word(@main::word_casing_arr) 
                {
                	chomp $word;
			$newfile =~ s/(^|\s+|_|\.)($word)(\s+|_|\.|\..{3,4}$)/$1.$word.$3/egi;
			if($tag) 
			{
				$newart =~ s/(^|\s+|_|\.)($word)(\s+|$)/$1.$word.$3/egi;
				$newtit =~ s/(^|\s+|_|\.)($word)(\s+|$)/$1.$word.$3/egi;
				$newalb =~ s/(^|\s+|_|\.)($word)(\s+|$)/$1.$word.$3/egi;
				$newcom =~ s/(^|\s+|_|\.)($word)(\s+|$)/$1.$word.$3/egi;
			}
                }
        }

	# 1st letter of filename should be uc

	if($main::case) 
	{
                $newfile =~ s/^(\w)/uc($1)/e;

                if($tag) 
                {
                	$newart =~ s/^(\w)/uc($1)/e;
                	$newtit =~ s/^(\w)/uc($1)/e;
                	$newalb =~ s/^(\w)/uc($1)/e;
                	$newcom =~ s/^(\w)/uc($1)/e;
                }
        }

	# Pad digits with 0

	if($main::pad_digits_w_zero) 
	{
		# rm extra 0's
		$newfile =~ s/(^|\s+|\.|_)(\d{1,2})(x0)(\d{2})(\s+|\.|_|\..{3,4}$)/$1.$2."x".$4.$5/ieg;

		# pad NxN
		$newfile =~ s/(^|\s+|\.|_)(\dx)(\d)(\s+|\.|_|\..{3,4}$)/$1."0".$2."0".$3.$4/ie;	# NxN to 0Nx0N
		$newfile =~ s/(^|\s+|\.|_)(\d\dx)(\d)(\s+|\.|_|\..{3,4}$)/$1.$2."0".$3.$4/ie;	# NNxN to NNx0N
		$newfile =~ s/(^|\s+|\.|_)(\dx)(\d\d)(\s+|\.|_|\..{3,4}$)/$1."0".$2.$3.$4/ie;	# NxNN to 0NxNN

		# clean scene style
		# rm extra 0's
		$newfile =~ s/(^s|\s+s|\.s|_s)(\d{1,2})(e0)(\d{2})(\s+|\.|_|\..{3,4}$)/$1.$2."e".$4.$5/ieg;

		$newfile =~ s/(^s|\s+s|\.s|_s)(\d)(e)(\d)(\s+|\.|_|\..{3,4}$)/$1."0".$2."0".$3.$4.$5/ie;	# sNeN to S0Ne0N
		$newfile =~ s/(^s|\s+s|\.s|_s)(\d\d)(e)(\d)(\s+|\.|_|\..{3,4}$)/$1.$2.$3."0".$4.$5/ie;		# sNNeN to sNNe0N
		$newfile =~ s/(^s|\s+s|\.s|_s)(\d)(e)(\d\d)(\s+|\.|_|\..{3,4}$)/$1."0".$2.$3.$4.$5/ie;		# SNeNN to S0NeNN
	}

	# Pad digits with " - " (must come after pad digits with 0 to catch any new

	if($main::pad_digits) 
	{
		# optimize me

		$tmp = " - ";
		$newfile =~ s/(\s+)(\d\d|\d+x\d+)(\s+)/$tmp.$2.$tmp/ie;
		$newfile =~ s/(\s+)(\d\d|\d+x\d+)(\..{3,4}$)/$tmp.$2.$3/ie;
		$newfile =~ s/^(\d\d|\d+x\d+)(\s+)/$1.$tmp/ie;
	}

	# ----------------------------------
	# Post General cleanup
	# ----------------------------------

        if($main::cleanup == 1) {
                # remove childless brackets () [] {}
                $newfile =~ s/(\(|\[|\{)(\s|_|\.|\+|-)*(\)|\]|\})//g;

                # remove doubled up -'s
                $newfile =~ s/-(\s|_|\.)+-|--/-/g;

                # rm trailing characters
                $newfile =~ s/(\s|\+|_|\.|-)+(\..{3,4})$/$2/;

                # rm leading characters
                $newfile =~ s/^(\s|\+|_|\.|-)+//;

                # rm extra whitespaces
                $newfile =~ s/\s+/ /g;
                $newfile =~ s/$main::space_character+/$main::space_character/g;

		# change file extension to lower case and remove anyspaces before file ext
                $newfile =~ s/^(.*)(\..{3,4})$/$1.lc($2)/e;

                if(-d $file)
                {
                	$newfile =~ s/(\s|\+|_|\.|-)+$//;
                }

                if($tag) 
                {
                	# remove childless brackets () [] {}
			$newart =~ s/(\(|\[|\{)(\s|_|\.|\+|-)*(\)|\]|\})//g;
                	$newtit =~ s/(\(|\[|\{)(\s|_|\.|\+|-)*(\)|\]|\})//g;
                	$newalb =~ s/(\(|\[|\{)(\s|_|\.|\+|-)*(\)|\]|\})//g;

			# remove leading / trailing whitspaces
                	$newart =~ s/(^\s+)|(\s+$)//g;
                	$newtit =~ s/(^\s+)|(\s+$)//g;
                	$newalb =~ s/(^\s+)|(\s+$)//g;
                	$newcom =~ s/(^\s+)|(\s+$)//g;
                }
        }

	# ----------------------------------
	# stuff todo after final cleanup
	# ----------------------------------

	# lowercase all
        if($main::lc_all) {
                $newfile = lc($newfile);
        }

	# uppercase all
        if($main::uc_all) {
                $newfile = uc($newfile);
        }

	# guess tag :P

	if($main::id3_guess_tag == 1 && $_ =~ /.*\.mp3$/)
        {
		($newart, $newtra, $newtit, $newalb) = &guess_tags($file);
	}

	# truncate file

	$l = length $newfile;
	if($l > $main::max_fn_length && $main::truncate == 0) 
	{
		&nf_print("$file", "ERROR: $newfile exceeds maximum filename length.\n");

		return;
	}
	if($l > $main::truncate_to && $main::truncate == 1) 
	{
		$file_ext = $newfile;
		$file_ext =~ s/^(.*)(\.)(.{3,4})$/$3/e;
		$file_ext_length = length $file_ext;	# doesnt include . in length

		# var for adjusted truncate to, gotta take into account file ext length
		$tl = $main::truncate_to - ($file_ext_length + 1);

		# adjust tl to allow for added enum digits if enum mode is enabled
		if($main::enum && $main::enum_pad) 
		{
			$tl = $tl - $main::enum_pad_zeros
		}
		elsif($main::enum) 
		{
			$tl = $tl - length "$main::enum_count";
		}

		# start truncating

		# from front
		if($main::truncate_style == 0) 
		{
			$newfile =~ s/^(.*)(.{$tl})(\..{$file_ext_length})$/$2.$3/e;
		}

		# from end
		elsif($main::truncate_style == 1) 
		{
 			$newfile =~ s/^(.{$tl})(.*)(\..{$file_ext_length})$/$1.$3/e;
		}

		# from middle
		elsif($main::truncate_style == 2) 
		{
			my $tl = int ($tl - length $main::trunc_char) / 2;

			$newfile =~ s/^(.{$tl})(.*)(.{$tl})(\..{$file_ext_length})$/$1.$main::trunc_char.$3.$4/e;
		}
	}


        if($main::space) 
        {
        	$newfile =~ s/\s+|_+/$main::space_character/g;
        }

	# Enumerate

	if($main::enum) 
	{
        	$enum_n = $main::enum_count;

        	if($main::enum_pad == 1) 
        	{
        		$a = "%.$main::enum_pad_zeros"."d";
        		$enum_n = sprintf($a, $enum_n);
 		}

        	if($main::enum_opt == 0) 
        	{
        		if(-d $file) 
        		{
        			$newfile = $enum_n;
        		}
        		else 
        		{
        			# numbers and file ext only
        			$newfile =~ s/^.*\././;
        			$newfile = "$enum_n"."$newfile";
        		}
        	} elsif($main::enum_opt == 1) 
        	{
			# Insert N at begining of filename
        	        $newfile = "$enum_n"."$newfile";
		} elsif($main::enum_opt == 2) 
		{
			# Insert N at end of filename but before file ext
			$newfile =~ s/(.*)(\..*$)/$1$enum_n$2/g;
		}
                $main::enum_count++;
	}
	# End of cleanups

	# set user entered tags if any

	if($main::id3_art_set && $file =~ /.*\.mp3$/i) {
		$newart = $main::id3_art_str;
		$tag	= 1;
	}

	if($main::id3_alb_set && $file =~ /.*\.mp3$/i) {
		$newalb = $main::id3_alb_str;
		$tag	= 1;
	}

	if($main::id3_gen_set && $file =~ /.*\.mp3$/i) {
		$newgen = $main::id3_gen_str;
		$tag	= 1;
	}

	if($main::id3_year_set && $file =~ /.*\.mp3$/i) {
		$newyear = $main::id3_year_str;
		$tag	= 1;
	}

	if($main::id3_com_set && $file =~ /.*\.mp3$/i) {
		$newcom = $main::id3_com_str;
		$tag	= 1;
	}

        if($main::id3v1_rm && $file =~ /.*\.mp3$/i) {
        	if(!$main::testmode) {
        		&rm_tags($file, "id3v1");
                }
                else {
                	$main::tags_rm++;
                }
                $tmp = "printme";
        }

        if($main::id3v2_rm && $_ =~ /.*\.mp3$/i) {
        	if(!$main::testmode) {
        		&rm_tags($file, "id3v2");
                }
                else {
                	$main::tags_rm++;
                }
                $tmp = "printme";
        }

        if($main::id3v1_rm && $main::id3v2_rm && $file =~ /.*\.mp3$/i) {
        	$tag = 0;
        }

	# no tags and no fn change

	if($tag == 0 && $file eq $newfile) {
        	if($tmp eq "printme") {
                	&nf_print($file, $newfile);
                }
		return;
	}

       	if($tag) {
       		# fn & tags havent changed

		if(
                	$main::id3_writeme == 0 &&
                	$file eq $newfile &&
               	 	$art eq $newart &&
	                $tit eq $newtit &&
	                $tra eq $newtra &&
	                $alb eq $newalb &&
	                $com eq $newcom &&
                        $gen eq $newgen &&
                        $year eq $newyear
        	) {
	        	if($tmp eq "printme") {
        	        	&nf_print($file, $newfile);
        	        }
        		return;
        	}

        	# one or more tags changed, write n bump counter

        	if(
                	$main::id3_writeme == 1 ||
                	$art ne $newart ||
	                $tit ne $newtit ||
	                $tra ne $newtra ||
	                $alb ne $newalb ||
	                $com ne $newcom ||
                        $gen ne $newgen ||
                        $year ne $newyear
        	) {
        		if(!$main::testmode) {
       				&write_tags($file, $newart, $newtit, $newtra, $newalb, $newcom, $newgen, $newyear);
       			}
       			$main::id3_change++;
       		}
	}

	# check for and apply filename changes

	if($file ne $newfile) 
	{
	        if($main::fat32fix) 
	        {
	                # work around case insensitive filesystem renaming problems

	                $tmpfile = $newfile."-FSFIX";

	                if( -e $tmpfile && !$main::overwrite) 
	                {
	                        $main::tmpfilefound++;
	                        $main::tmpfilelist .= "$tmpfile\n";
	                        return;
	                }

	                if (!$main::testmode) 
	                {
	                        rename $file, $tmpfile;
	                        if(-e $newfile && !$main::overwrite) 
	                        {
					&nf_print("$file", "ERROR: $newfile allready exists - fs fix mode");
	                  		rename $tmpfile, $file;

	                  		return;
	                        }
	                        else {
	                        	rename $tmpfile, $newfile;
	                        }
	                }
	        }
	        elsif(!$main::testmode) 
	        {
	                if(-e $newfile && !$main::overwrite) 
	                {
	                        $main::suggestF++;
				&nf_print("$file", "ERROR: $newfile allready exists - normal mode");

	                        return;
	                }
	                else 
	                {
	                	rename $file, $newfile;
			}
	        }
		$main::change++;
	}

        if($tag) 
        {
        	&nf_print
        	(
                	$file,
                        $newfile,

                        $art,
                        $tit,
                        $tra,
                        $alb,
                        $com,
                        $gen,
                        $year,

                        $newart,
                        $newtit,
                        $newtra,
                        $newalb,
                        $newcom,
                        $newgen,
                        $newyear
                );
        }
        else {
        	&nf_print("$file", "$newfile");
	}
};


1;

syntax highlighted by Code2HTML, v. 0.9.1