#!/usr/bin/perl
# $Id: licq2kopete,v 1.2 2002/06/12 01:12:38 perreaul Exp $
#
# licq2kopete - Convert licq contact list to Kopete format
# Copyright (C) 2002  Simon Perreault <nomis80@linuxquebec.com>
#
# 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 2
# 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.

use strict;

# A simple warning
print "Please make sure Kopete is not running. Press ENTER to continue...\n";
<STDIN>;

my $timestart = time;

chomp( my $CONFIG = `kde-config --localprefix` );
unless ($CONFIG) {
    if ( -d "$ENV{HOME}/.kde3" ) {
        $CONFIG = "$ENV{HOME}/.kde3";
    }
    elsif ( -d "$ENV{HOME}/.kde" ) {
        $CONFIG = "$ENV{HOME}/.kde";
    }
    else {
        die "Couln't find kde configuration directory\n";
    }
}

# Parce licq's main config file and get the groups contacts may be members of
my $licqconf = parseRC("$ENV{HOME}/.licq/licq.conf");
my @new_groups;
for ( my $i = 1 ; $i <= $licqconf->{groups}{groups}{NumOfGroups} ; $i++ ) {
    push @new_groups, $licqconf->{groups}{groups}{"Group$i.name"};
}

# Now a licq contact member of group x is in fact member of $new_groups[x-1]

# Parse Kopete's main config file
my $kopeterc = parseRC("$CONFIG/share/config/kopeterc");

my @groups = split /,/, $kopeterc->{groups}{ContactList}{Groups};

# We also create a hash of the groups so that we can be very fast (in case
# someone has a zillion groups) instead of doing a linear search
my %groups = map { $_ => 1 } @groups;

# Add the "Unknown" contact group (or make sure it's already there)
push @groups, 'Unknown' unless $groups{Unknown};
$groups{Unknown} = 1;

# Also add the groups defined in licq.conf, they are now in @new_groups 
foreach (@new_groups) {
    push @groups, $_ unless $groups{$_};
    $groups{$_} = 1;
}

# Put the groups back into the data structure
$kopeterc->{groups}{ContactList}{Groups} = join ",", @groups;

# Build a hash so that we can map groupname to groupindex
my %group2index;
for ( my $i = 0 ; $i < @groups ; $i++ ) {
    $group2index{ $groups[$i] } = $i + 1;
}

# Get the contacts from Licq
my $licqContacts = parseRC("$ENV{HOME}/.licq/users.conf");

my @oldcontacts;
for ( my $i = 1 ; $i <= $licqContacts->{groups}{users}{NumOfUsers} ; $i++ ) {
    my $contact = {};
    $contact->{uin} = $licqContacts->{groups}{users}{"User$i"};
    my $contactInfo = parseRC("$ENV{HOME}/.licq/users/$contact->{uin}.uin");
    $contact->{nick}     = $contactInfo->{groups}{user}{Alias};
    $contact->{cellular} = $contactInfo->{groups}{user}{CellularNumber};

    # Now determine the group index of the contact
    if ( $contactInfo->{groups}{user}{'Groups.User'} != 0 ) {
        # This user is not a member of the default group, and will not go into
        # 'Unknown'
        $contact->{group} =
          $group2index{ $new_groups[ $contactInfo->{groups}{user}
              {'Groups.User'} - 1 ] };
    }
    else {
        # Not a member of any group, store into 'Unknown'
        $contact->{group} = $group2index{Unknown};
    }

    push @oldcontacts, $contact;
}

# Parse the icq.contacts file
my $icqContacts = parseRC( "$CONFIG/share/apps/kopete/icq.contacts", 'nowarn' );

# Put the old contacts into kopete's config
foreach (@oldcontacts) {
    $icqContacts->{groups}{"Contact $_->{uin}"} = {
        Authorized => 'true',
        Group      => $_->{group},
        Nick       => $_->{nick},
        UIN        => $_->{uin},
    };
    $icqContacts->{groups}{"Contact $_->{uin}"}{Cellular} = $_->{cellular}
      if $_->{cellular};
    print ".";
}

# Setup some defaults
my %contacts = map { $_ => 1 } split /,/,
  $icqContacts->{groups}{Default}{Contacts};
$contacts{ $_->{uin} } = 1 foreach @oldcontacts;
$icqContacts->{groups}{Default}{Contacts} = join ",", keys %contacts;
$icqContacts->{groups}{Default}{Count} = keys %contacts;
$icqContacts->{groups}{Default}{"Group ID Count"} = @groups;
$icqContacts->{groups}{Default}{"Group IDs"}      = join ",",
  ( 1 .. scalar @groups );
$icqContacts->{groups}{Default}{"Group Names"} =
  $kopeterc->{groups}{ContactList}{Groups};

system 'cp', "$CONFIG/share/config/kopeterc",
  "$CONFIG/share/config/kopeterc.bak"
  if -f "$CONFIG/share/config/kopeterc";
system 'cp', "$CONFIG/share/apps/kopete/icq.contacts",
  "$CONFIG/share/apps/kopete/icq.contacts.bak"
  if -f "CONFIG/share/config/kopeterc";
storeRC( $kopeterc,    "$CONFIG/share/config/kopeterc" );
storeRC( $icqContacts, "$CONFIG/share/apps/kopete/icq.contacts" );

print "\n"
  . @oldcontacts
  . " contacts converted in "
  . ( time - $timestart )
  . " seconds.\n";

################################################################

# Input: The name of a file which is in the form of a KConfig file
#        (optional) a flag to not print a warning if the file can't be opened
# Output: A reference to a hash containing the parsed info.
sub parseRC {
    my $file   = shift;
    my $nowarn = shift;

    open RC, $file;
    local $/;
    my $rc = <RC>;
    close RC;

    my @groups = split /\n{2,}/, $rc;
    my %rc;
    foreach my $group (@groups) {
        if ( $group =~ s/^\s*\[(.+?)\]\n//s ) {
            my $groupID = $1;
            foreach my $line ( split /\n/, $group ) {
                my ( $key, $value ) = $line =~ /^(.+?)\s*=\s*(.*)/;
                $rc{groups}{$groupID}{$key} = $value;
            }
        }
        else {
            foreach my $line ( split /\n/, $group ) {
                my ( $key, $value ) = $line =~ /^(.+?)\s*=\s*(.*)/;
                $rc{general}{$key} = $value;
            }
        }
    }
    return \%rc;
}

# Input: A reference to a hash containing a parsed RC file,
#        A file name where to store the information.
# Output: None.
sub storeRC {
    my $rc_ref = shift;
    my $file   = shift;

    open RC, '>', $file or warn "Can't open $file for writing: $!\n";

    foreach ( sort keys %{ $rc_ref->{general} } ) {
        print RC "$_=$rc_ref->{general}{$_}\n";
    }
    print RC "\n" if $rc_ref->{general};

    foreach my $group ( sort keys %{ $rc_ref->{groups} } ) {
        print RC "[$group]\n";
        foreach ( sort keys %{ $rc_ref->{groups}{$group} } ) {
            print RC "$_=$rc_ref->{groups}{$group}{$_}\n";
        }
        print RC "\n";
    }

    close RC;
}
