#!/usr/bin/perl
#
# <LJDEP>
# lib: cgi-bin/ljlib.pl
# </LJDEP>

use strict;
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "$ENV{'LJHOME'}/cgi-bin/ljviews.pl";

my $dbh = LJ::get_db_writer();

sub header_text {
    return <<"HEADER";
# This file is automatically generated from MySQL by \$LJHOME/bin/dumpsql.pl
# Don't submit a diff against a hand-modified file - dump and diff instead.

HEADER
}

# what tables don't we want to export the auto_increment columns from
# because they already have their own unique string, which is what matters
my %skip_auto = ("userproplist" => "name",
                 "talkproplist" => "name",
                 "logproplist" => "name",
                 "priv_list" => "privcode",
                 "supportcat" => "catkey",
                 "ratelist" => "rlid",
                 );

# get tables to export
my %tables = ();
my $sth = $dbh->prepare("SELECT tablename, redist_mode, redist_where ".
                        "FROM schematables WHERE redist_mode NOT IN ('off')");
$sth->execute;
while (my ($table, $mode, $where) = $sth->fetchrow_array) {
    $tables{$table}->{'mode'} = $mode;
    $tables{$table}->{'where'} = $where;
}

my %output;  # {general|local} -> [ [ $alphasortkey, $SQL ]+ ]

# dump each table.
foreach my $table (sort keys %tables)
{
    my $where;
    if ($tables{$table}->{'where'}) {
        $where = "WHERE $tables{$table}->{'where'}";
    }

    my $sth = $dbh->prepare("DESCRIBE $table");
    $sth->execute;
    my @cols = ();
    my $skip_auto = 0;
    while (my $c = $sth->fetchrow_hashref) {
        if ($c->{'Extra'} =~ /auto_increment/ && $skip_auto{$table}) {
            $skip_auto = 1;
        } else {
            push @cols, $c;
        }
    }

    # DESCRIBE table can be different between developers
    @cols = sort { $a->{'Field'} cmp $b->{'Field'} } @cols;

    my $cols = join(", ", map { $_->{'Field'} } @cols);
    my $sth = $dbh->prepare("SELECT $cols FROM $table $where");
    $sth->execute;
    my $sql;
    while (my @r = $sth->fetchrow_array)
    {
        my %vals;
        my $i = 0;
        foreach (map { $_->{'Field'} } @cols) {
            $vals{$_} = $r[$i++];
        }
        my $scope = "general";
        $scope = "local" if (defined $vals{'scope'} &&
                             $vals{'scope'} eq "local");
        my $verb = "INSERT IGNORE";
        $verb = "REPLACE" if ($tables{$table}->{'mode'} eq "replace" &&
                              ! $skip_auto);
        $sql = "$verb INTO $table ";
        $sql .= "($cols) ";
        $sql .= "VALUES (" . join(", ", map { db_quote($_) } @r) . ");\n";

        my $uniqc = $skip_auto{$table};
        my $skey = $uniqc ? $vals{$uniqc} : $sql;
        push @{$output{$scope}}, [ "$table.$skey.1", $sql ];

        if ($skip_auto) {
            # for all the *proplist tables, there might be new descriptions
            # or columns, but we can't do a REPLACE, because that'd mess
            # with their auto_increment ids, so we do insert ignore + update
            my $where = "$uniqc=" . db_quote($vals{$uniqc});
            delete $vals{$uniqc};
            $sql = "UPDATE $table SET ";
            $sql .= join(",", map { "$_=" . db_quote($vals{$_}) } sort keys %vals);
            $sql .= " WHERE $where;\n";
            push @{$output{$scope}}, [ "$table.$skey.2", $sql ];
        }
    }
}

# don't use $dbh->quote because it's changed between versions
# and developers sending patches can't generate concise patches
# it used to not quote " in a single quoted string, but later it does.
# so we'll implement the new way here.
sub db_quote {
    my $s = shift;
    return "NULL" unless defined $s;
    $s =~ s/\\/\\\\/g;
    $s =~ s/\"/\\\"/g;
    $s =~ s/\'/\\\'/g;
    $s =~ s/\n/\\n/g;
    $s =~ s/\r/\\r/g;
    return "'$s'";
}

foreach my $k (keys %output) {
    my $file = $k eq "general" ? "base-data.sql" : "base-data-local.sql";
    print "Dumping $file\n";
    my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file";
    open (F, ">$ffile") or die "Can't write to $ffile\n";
    print F header_text();
    foreach (sort { $a->[0] cmp $b->[0] } @{$output{$k}}) {
        print F $_->[1];
    }
    close F;
}

# and do S1 styles (ugly schema)
print "Dumping s1styles.dat\n";
require "$ENV{'LJHOME'}/bin/upgrading/s1style-rw.pl";
my $ss = {};
my $pubstyles = LJ::S1::get_public_styles({ 'formatdata' => 1});
foreach my $s (values %$pubstyles) {
    my $uniq = "$s->{'type'}/$s->{'styledes'}";
    $ss->{$uniq}->{$_} = $s->{$_} foreach keys %$s;
}
s1styles_write($ss);

# and dump mood info
print "Dumping moods.dat\n";
open (F, ">$ENV{'LJHOME'}/bin/upgrading/moods.dat") or die;
$sth = $dbh->prepare("SELECT moodid, mood, parentmood FROM moods ORDER BY moodid");
$sth->execute;
while (@_ = $sth->fetchrow_array) {
    print F "MOOD @_\n";
}

$sth = $dbh->prepare("SELECT moodthemeid, name, des FROM moodthemes WHERE is_public='Y' ORDER BY name");
$sth->execute;
while (my ($id, $name, $des) = $sth->fetchrow_array) {
    $name =~ s/://;
    print F "MOODTHEME $name : $des\n";
    my $std = $dbh->prepare("SELECT moodid, picurl, width, height FROM moodthemedata ".
                            "WHERE moodthemeid=$id ORDER BY moodid");
    $std->execute;
    while (@_ = $std->fetchrow_array) {
	print F "@_\n";
    }
}
close F;


print "Done.\n";
