#!/usr/bin/perl

use DBI;
use Data::Dumper;
use Time::ParseDate;
use POSIX;
use strict;

# Source DB
my $sdb = DBI->connect("dbi:Pg:dbname=$ARGV[0]") or die;
$sdb->do("SET client_encoding=\'UTF8\'") or die;
#my $sdb = DBI->connect("dbi:mysql:dbname=$ARGV[0]") or die;
#$sdb->do("SET names \'utf8\'"); #character_set_client = utf8");

# Destination DB
my $tdb = DBI->connect("dbi:Pg:dbname=$ARGV[1]") or die;
$tdb->do("SET client_encoding=\'UTF8\'") or die;
## MySQL not supported due to sequence value change

my $map_table = $ARGV[2] || 'migrate_map_1';

$|=1;

$tdb->do("delete from comments");
$tdb->do("update node_comment_statistics set comment_count=0");

my $maxid = 1;
my $migrate_map = $tdb->selectall_hashref("select sourceid,destid from $map_table",'sourceid');

for my $sid(keys %$migrate_map)
  {
    my $comments = select_comments($sid);
    insert_comments($migrate_map->{$sid}->{destid},$comments) if $comments;
  }

$tdb->do("select setval('comments_cid_seq',$maxid)");


sub select_comments
  {
    my $entry_id = shift or return undef;
    my $comments = $sdb->selectall_hashref("select * from mt_comment where comment_visible>0 and comment_entry_id=?",'comment_id',
                                           undef,$entry_id);
    return undef unless $comments;
    foreach my $cid(keys %$comments)
      {
        $comments->{$cid}->{author_id} = lookup_author($comments->{$cid});
        $comments->{$cid}->{timestamp} = parsedate($comments->{$cid}->{comment_created_on});
      }
    return $comments;
  }


sub insert_comments
  {
    my ($nid,$chash)=@_;
    my $ins = $tdb->prepare("insert into comments (cid,pid,nid,uid,subject,comment,hostname,timestamp,status,format,thread,name,mail,homepage) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
    my $maxcid = 1;
    my ($lastts,$lastauthor,$lastuid);
    my %thash=('0/'=>1);

    # First comments first b/c of sorting. Calculate thread ids
    for my $cid( sort {$a<=>$b} keys %$chash)
      {
        my @tlist = sort keys %thash;
        # Perl from PHP+SQL translation (from comment.module)
        if ($chash->{$cid}->{comment_parent_id})
          {
            my $pthread = $chash->{$chash->{$cid}->{comment_parent_id}}->{thread};
            $pthread=~s|/$||;
            my $plen = length $pthread;
            # search for max value in this thread
            my %th;
            foreach my $t(keys %$chash)
              {
                next unless $chash->{$t}->{thread};
                my $ot = $chash->{$t}->{thread};
                next if $t eq $cid; # not me!
                if ($pthread."." eq substr($ot,0,$plen+1))
                  {
                    $th{$ot}=1;
                  }
              }
            my @tl = sort keys %th;
            if (@tl)
              {
                my $max = $tl[$#tl];
                $max=~s|/$||;
                my @m = split(/\./,$max);
                my $last = $m[$#m];
                my $thread = $pthread . '.'.int2vancode(vancode2int($last)+1)."/";
                $chash->{$cid}->{thread}=$thread;
              }
            else
              {
                # first child of this parent
                my $thread = $pthread .'.'.int2vancode(0)."/";
                $chash->{$cid}->{thread}=$thread;
              }
          }
        else
          {
            # new thread
            my $maxt = $tlist[$#tlist];
            $maxt=~s/\/$//;
            my $thread = int2vancode(vancode2int($maxt)+1)."/";
            $chash->{$cid}->{thread}=$thread;
          }
        $thash{$chash->{$cid}->{thread}}=1 if $chash->{$cid}->{thread};
#        print " $cid| $chash->{$cid}->{comment_parent_id} : $chash->{$cid}->{thread} : $cnt\n";
#        $cnt++;
      }
    # real insertt
    my $cnt=0;
    for my $cid( sort {$a<=>$b} keys %$chash)
      {
        my $item = $chash->{$cid};
        $ins->execute(
                      $cid,
                      $item->{comment_parent_id}||0,
                      $nid,
                      $item->{author_id}, # created on read phase
                      "", # subject
                      $item->{comment_text},
                      $item->{comment_ip},
                      $item->{timestamp},
                      0,
                      1,
                      $item->{thread},
                      $item->{comment_author},
                      $item->{comment_email},
                      $item->{comment_url}
                     );
        $cnt++;
        if ($cid > $maxcid)
          {
            $maxcid=$cid;
            $lastts = $item->{timestamp};
            $lastauthor = $item->{comment_author};
            $lastuid = $item->{author_id};
          }
        # global max comment id
        $maxid = $cid if $cid>$maxid;
      }
    print "$nid=>$cnt\n";
    $tdb->do("update node_comment_statistics set last_comment_timestamp=?,last_comment_name=?,last_comment_uid=?,comment_count=? where nid=?",undef,$lastts,$lastauthor,$lastuid,$cnt,$nid) if $cnt;
  }

sub lookup_author
  {
    my $item = shift or return 0;
    if ($item->{comment_author}=~/tutubalin/i)
      {
        return 1;
      }
    return 0;
  }


sub base36
  {
    my $i=shift || 0;
    my @nums=(0..9,'a'..'z')[0..35];
    my $base = 36;
    return $nums[0] if $i == 0;
    my $rep="";
    while ($i>0)
      {
        $rep = $nums[$i%$base].$rep;
        $i = int($i/$base);
      }
    return $rep;
  }

sub frombase36
  {
    my $rep=shift || "";
    my @nums=(0..9,'a'..'z')[0..35];
    my $index = 0;
    my %nums = map {$_,$index++} @nums;
    my $base = 36;
    my $number=0;
    for (split(//,$rep))
      {
        $number *= $base;
        $number += $nums{$_};
      }
    return $number;
  }

sub vancode2int
  {
    my $code = shift || "0";
    return frombase36(substr($code,1));
  }

sub int2vancode
  {
    my $i = shift || 0;
    my $num = base36(int($i));
    my $length = length($num);
    return chr($length + ord('0') - 1) . $num;
}


