#!/usr/bin/perl -w
use strict;

##############################################
#                                            #
#       pine2mutt 0.3 - A Pine to Mutt       #
#          Address Book Converter            #
#         written by Jan Schaumann           #
#                                            #
#   pine2mutt 0.3 is published under the     #
#     GPL and comes with no warranty         #
#                 whatsoever                 #
#                                            #
#  You can obtain pine2mutt 0.3 (or maybe    #
#      even more recent versions) from       #
#         http://www.netmeister.org          #
#                                            #
#       Please send all Bug-Reports to       #
#          <jschauma@netmeister.org>         #
#                                            #
#     This program is Free Software and      #
# is published under the GNU Public License  #
#         see COPYING for details            #
#                                            #
##############################################

use Getopt::Std;

my $OUT		=  "$ENV{HOME}/.pine2mutt";
my $VERSION	= "0.3";
my $NAME 	= "pine2mutt";

sub getAddresses;
sub keyBindings;
sub sentFolder;
sub init;
sub main;

##

init();
main();

#we're done - bye, bye
exit 0;

###               ###
###   Functions   ### 
###               ###

###
# parses command-line options etc.
###
sub init
{
		my %Options;
		my $ok = getopts('hi:o:v', \%Options);
		if (!$ok)
		{
				my $i;
				my @values = keys(%Options);
				foreach $i (@values)
				{
						if (!$Options{$i})
						{
								print STDERR "Option '$i' requires an argument.\n";
								print STDERR "Try $NAME -h for details.\n";
								exit(1);
						}
				}
		}
		open (READ, "<&STDIN") ||
				die "Can't read from STDIN-- WTF??\n";


		if ($Options{'h'})
		{
				usage();
				exit 0;
		}
		if ($Options{'v'})
		{
				print "$NAME Version $VERSION\n";
				exit 0;
		}
		if ($Options{'i'})
		{
				open(READ, "$Options{'i'}") ||
						die "Can't open \"$Options{'i'}\" for reading!\n";
		}
		if ($Options{'o'})
		{
				open(WRITE, ">$Options{'o'}") ||
						die "Can't open \"$Options{'o'}\" for writing!\n";
				$OUT = $Options{'o'};
		}

		open (WRITE, ">$OUT") ||
				die "Can't write to $OUT: $!\n";

		if ($#ARGV > -1)
		{
				usage();
				exit(1);
		}
}

###     
# prints out helpful information
###             
sub usage       
{       
		print "$NAME: make mutt behave more like pine\n";
		print "Usage: $NAME [OPTION...]\n";
		print "Options:\n";
		print "  -h\t\tprint this message and exit\n";
		print "  -i FILE\tread input from FILE [ default: STDIN ]\n";
		print "  -o FILE\twrite output to FILE [ default: ~/.pine2mutt ]\n";
		print "  -v\t\tprint version number and exit\n";
}


###
# start the manipulation
###
sub main
{
		print WRITE "# addresses imported from pine through pine2mutt(1)\n\n";
		getAddresses();
		print WRITE "\n";
		keyBindings();
		print WRITE "\n";
		sentFolder();

		### now tell .muttrc where to look for pine-stuff

		my $found = 0;

		if ( -f "$ENV{HOME}/.muttrc" )
		{
				open(MUTTRC, "$ENV{HOME}/.muttrc") or die "$!\n";
				while(<MUTTRC>)
				{
						if (/source $OUT/)
						{
								$found = 1;
						}
				}
		}

		if (!$found)
		{
				open(MUTTRC, ">>$ENV{HOME}/.muttrc") or die "Can't open $ENV{HOME}/.muttrc!\n";
				print MUTTRC "\n###\n# aliases and pine-like keybindings from pine2mutt\n";
				print MUTTRC "# WARNING - these might overwrite otherwise specified bindings\n";
				print MUTTRC "# You should probably check that file to make sure all's well\n###\n";
				print MUTTRC "source $OUT \n";
		}
		close(MUTTRC);
		close(WRITE);
		close(READ);
}

###
# convert pine-like addresses
###
sub getAddresses
{

		my $nick;
		my $name;
		my $email;
		my $tmp;

		while (<READ>)
		{

				next if /^#DELETED/;	# pine keeps deleted email-addresses for a while

				if (s/\(//)				# pine has email-lists in parentheses
				{
										# skip if it does not have three tabs:
						next unless ($nick, $name, $tmp) = /(.*?)\t(.*?)\t(.*?)$/;
				}
				else
				{
						unless (/^\s/)	# ^\s means an email-list continues 
						{
										# a normal entry is nick\tname\temail:
								next unless ($nick, $name, $email) = /(.*?)\t(.*?)\t(.*?)$/;

										# sometimes additional information is appended 
										# to the email in $4:
								$email =~ s/(.*?)\s(.*?)$/$1/;

								print WRITE "alias $nick $email ($name)\n";
						}
				}

				if (($tmp) and (/^\s/))	# we have an email-list
				{
						if (s/\)//)		# end of the email-list
						{
								$tmp = $tmp . $_;
								$tmp =~ s/\s//g;
								$email = $tmp;
								print WRITE "alias $nick $email ($name)\n";	
						}
						else
						{
								$tmp = $tmp . $_;
						}
				}
		}
}

###
# pine-like key-bindings
###
sub keyBindings
{
		# contents from Pine.rc, part of the mutt distribution
		# we used to use "locate" here to source it in the new file,
		# but not all systems use "locate"

		print WRITE "# Pine-like keybindings follow:\n";
		print WRITE "bind index v display-message\n";
		print WRITE "bind index p previous-undeleted\n";
		print WRITE "bind index n next-undeleted\n";
		print WRITE "bind index ' ' next-page\n";
		print WRITE "bind index c mail\n";
		print WRITE "bind index g change-folder\n";
		print WRITE "bind index w search\n";
		print WRITE "bind index y print-message\n";
		print WRITE "bind index x sync-mailbox\n";
		print WRITE "bind index \$ sort-mailbox\n";
		print WRITE "bind index a tag-prefix\n";
		print WRITE "bind index \\; tag-entry\n";
		print WRITE "\n";
		print WRITE "# Not possible to simulate zoom-out...\n";
		print WRITE "macro index z l~T\\r\n";
		print WRITE "\n";
		print WRITE "bind pager p previous-undeleted\n";
		print WRITE "bind pager n next-undeleted\n";
		print WRITE "bind pager ' ' next-page\n";
		print WRITE "bind pager g change-folder\n";
		print WRITE "bind pager c mail\n";
		print WRITE "bind pager w search\n";
		print WRITE "bind pager y print-message\n";
		print WRITE "bind pager \\n noop  # PINE prints \"No default action for this menu.\"\n";
		print WRITE "bind pager <up> previous-line\n";
		print WRITE "bind pager <down> next-line\n";
		print WRITE "\n";
		print WRITE "bind compose \cx send-message\n";
		print WRITE "\n";
		print WRITE "# PINE has different defaults for this variables\n";
		print WRITE "set folder=~/mail\n";
		print WRITE "set record=+sent-mail\n";
		print WRITE "set nosave_name\n";
		print WRITE "set postponed=~/postponed-msgs\n";
		print WRITE "set hdr_format=\"\%Z \%3C \%{\%b \%d} \%-19.19L (\%5c) \%s\"\n";
}

###
# pine-like sent-folder
###
sub sentFolder
{
		my $found = 0;
		my $record;

		return unless -f "$ENV{HOME}/.muttrc";

		open(MUTTRC, "$ENV{HOME}/.muttrc") or die "$!\n";
		while(<MUTTRC>)
		{
				if (/set record/)
				{
						$found = 1;
						chomp($record = $_);
				}
		}

		if ($found)
		{
				print WRITE "\n\n###\n# WARNING - this overwrites\n";
				print WRITE "# \"$record\"\n";
				print WRITE "# from $ENV{HOME}/.muttrc\n";
		}
		else
		{
				print WRITE "\n\n###\n# Pine-like sent-folder handling\n";
		}

		print WRITE "# Mutt does not delete the sent-folder at the end of the month\n";
		print WRITE "# if you want this, you need to set up a crontab-entry\n";
		print WRITE "###\n";
		print WRITE "set record=\"=sent-mail-`date +%b-%Y`\"\n";
}

